图论(树)笔记

图论(树)讲解部分

随机树据

在题目中树为纯随机生成时,会有一些额外的性质:

  • 当第 \(i\) 个点的父亲在 \([1, i − 1]\) 中等概率随机选取,那么树的高度期望为\(O(log n)\)
  • 当树从所有有标号无根树中随机选取,那么树的高度期望为 \(O(\sqrt{n})\)

树上倍增

倍增在关于树的问题中是一种非常常用的技巧,特别是在刻画树上路径时。

倍增本质上是对一个点到根形成的序列的某个子列的刻画,并不局限于 \(2^k\)

级父亲。同时因此,倍增在最深公共祖先问题中在某些方面比其他算法更优秀。

例题1:

题面

给定一棵树,初始时只有根一个点,你需要维护如下操作:

  • 给定 \(u\),假如现在树上有 \(n\) 个节点,那么新增一个父亲为 \(u\),编号为 \(n + 1\)的叶子节点。
  • 给定 \(u, v\),询问这两个的 lca。

强制在线,操作共 \(n\) 次。

\(1 \le n \le 3 \times 105\)

思路

我们尝试使用倍增来求 lca,注意到加入节点 \(i\) 时,所有 \(i\) 的祖先的倍增数

组已经求出,我们可以直接利用来求出 \(i\) 的倍增数组。所以加入一个叶子的复杂度就是 \(O(log n)\)

总复杂度 \(O(n log n)\)

[省选联考 2021 A/B 卷] 宝石

题面

给定 \(n\) 个点的树,每个节点有一种宝石,第 \(i\) 个节点宝石种类为 \(w_i\),宝石
总共有 \(m\) 种。

你有一个宝石收集器。这个宝石收集器能按照顺序收集至多 \(c\) 颗宝石,其

收集宝石的顺序为:\(P_1, P_2 \dots P_c\)。更具体地,收集器需要先放入第 \(P_1\) 种宝

石,然后才能再放入第 \(P_2\) 种宝石,之后再能放入第 \(P_3\) 种宝石,以此类推。其中 \(P_1, P_2 \dots P_c\) 互不相等。

你到达一个点后,如果该点上宝石种类和当前收集器中需要放入的种类相同,则你可以把一个该种宝石放进收集器。

询问 \(q\) 次,每次给出起点 \(s_i\) 与终点 \(t_i\),你需要回答,如果你走从 \(s_i\)\(t_i\)的最短路,收集器中最多能收集到几

个宝石?(在每次询问中,收集器内初始时没有任何宝石。起点与终点城市集市上的宝石可以尝试被收集)

\(1 \le n, q \le 2 \times 105,1 \le c \le m \le 5 × 104,1 \le wi \le m\)

思路

考虑二分答案 \(x\),如何判定。记 \(l = lca(s_i, t_i)\),把路线拆成 \(s_i\)\(l\)\(l\)\(t_i\)两部分。

对于宝石种类为 \(P_i\) 的点 \(u\),记 \(f_u,0\) 为它向上第一个种类为 \(P_i+1\) 的点,

\(g_u,0\) 为它向上第一个种类为 \(P_i−1\) 的点,然后记\(f_{u,j} = f_{fu,j−1,j−1, gu,j }= g_{gu,j−1,j−1}\)
\(U\)\(s_i\) 向上第一个种类为 \(P_1\) 的点(包括自己),\(V\)\(t_i\) 向上第一个种类为 \(P_x\) 的点(包括自己),那么就利用 $f, g $倍增判定 \(x\) 是否可行即可。
复杂度 \(O((n + q)log_2n)\)

树上差分

当需要对链进行操作,可以离线的时候,树上差分非常好用。

树上差分本质上是维护父亲减去所有儿子的差分数组,使得对链修改时只需要改 \(O(1)\) 个点,还原时也可以 \(O(n)\) 全部还原。

[NOIP2015 提高组] 运输计划

题面

给定一个点数为 \(n\) 的带非负边权的树,以及树上的 \(m\) 条链(可能有交),一条链的长度为链上所有边的边权和。

你现在可以把恰好一条边的边权变为 \(0\),你需要使得这 \(m\) 条链的长度的最大值最小。

\(1 \le n, m \le 3 \times 105\)

思路

我们可以二分答案 \(x\),对于链长已经小于等于 \(x\) 的链,我们可以忽略,那么我们只需要求出一条边权最大的边,使得剩余所有链都包含这条边。

我们预处理 lca 后,就可以用树上差分在 \(O(n + m)\) 的复杂度内求出每条边被多少条链包含。

复杂度 \(O((n + m)log n + (n + m)log W)\),其中 \(W\) 为边权和。

LCA技巧

考虑对于有根树而言,求 \(dep_{lca(u,v)}\) 可以视为,对 \(u\) 到根的路径链加一,然后求 \(v\) 到根路径上的和。

[LNOI2014] LCA

题面

给出一个 \(n\) 个节点的有根树。一个点的深度定义为这个节点到根的距离 \(+1\)

\(dep[i]\) 表示点 \(i\) 的深度,\(LCA(i, j)\) 表示 \(i\)\(j\) 的最近公共祖先。

\(m\) 次询问,每次询问给出 \(l, r, z\)

\(\sum_{i=l}^r dep[LCA(i,z)]\)

\(1 \le n, m \le 50000。\)

思路

离线,将\(\sum_{i=l}^r dep[LCA(i,z)] 拆成\sum_{i=1}^r dep[LCA(i,j)]和\sum_{i=1}^{l-1} dep[LCA(i,z)]\)

\(\sum_{i=1}^r dep[LCA(i,j)]\),相当于令\(\forall 1 \le i \le r\) ,到根的路径加一,然后询问\(z\)到根的链和。对询问排序后重链剖分即可。

时间复杂度 \(O((n + q)log^2n)\)

长链剖分

在题目与树的深度/链长/直径有关的时候,长链剖分是一种常见的技巧。

特别是在 dp 状态涉及子树深度时,长剖可以用来优化 dp。

长链剖分和重链剖分类似,设子树深度最深的儿子作为长儿子,其他为短儿子,长儿子对应的边为长边,连通的长边构成长链。可以证
明,从任意点到根节点至多经过 \(O(\sqrt{n})\) 条长链。

同时,由于长链的性质,可以很快地解决一些和深度有关的问题,比如
\(O(n log n) − O(1)\)\(k\) 级祖先

[POI2014]Hotel 加强版

题面

给定大小为 \(n\) 的树,边权全为 \(1\),求三元组 \((i, j, k)\) 的数量使得\(1 \le i < j < k \le n\)\(i, j, k\) 在树上两两的距离完全相同。

\(1 \le n \le 105\)

思路

\(f_{u,j}\)\(u\) 子树内离 \(u\) 距离恰为 \(j\) 的点的数量。
\(g_u,j\)\(u\) 子树内,满足如下条件的点对 \(v, w\) 的数量:令 $v, w $ 的 lca 为
\(l\),那么 \(v, w\)\(l\) 的距离相等且 \(l\)\(u\) 的距离恰为 \(v\)\(l\) 的距离减 \(j\)
写出转移式子,当加入 \(u\) 的儿子 \(v\) 时:

  • \(ans ← g_{v,j}f_{u,j−1} + g_{u,j}f_{v,j−1}\)
  • \(g_{u,j+1} ← f_{u,j+1}f_{v,j}\)
  • \(f_{u,j+1} ← f_{v,j}\)
  • \(g_{u,j−1} ← g_{v,j}\)
    注意到,如果暴力转移,那么复杂度是 \(O(len_v)\),其中 \(len_v\)\(v\) 子树的深
    度。同时,从长儿子继承状态是 \(O(1)\) 的。所以总复杂度是所有长链的长度和
    即为 \(O(n)\)

树的重心

直径和重心都是树非常重要的特征。重心的定义为使得删去后剩余子树最大点数最小的点,但是它有其他更有用的定义。

[ZJOI2015] 幻想乡战略游戏

题面

给定 \(n\) 个点的无根树,点有非负点权 \(d_i\),边有正边权。有 \(Q\) 次操作:
修改某个 \(d_i\),保证修改后 \(d_i\) 非负。
查询:$$min_u{\sum_{i=1}^{n} dis(u,i) d_i}$$

其中 $ dis(u, v)$ 为 \(u, v\) 两个点在树上的最短距离。

\(1 \le n, Q \le 105\)
原题作为动态点分树板子还有个每个点度数不超过 \(20\) 的限制,但是我们有一个更简单的做法不需要这个限制。

思路

事实上,使得要求式子最小的点 \(u\) 即为树的带权重心,这也是重心的其中一个定义。

我们令 \(1\) 作为根,求出每个子树点权和 \(sz_i\),那么重心就是满足$sz_1 \le 2sz_u $且使得 szu 最小的 u,这是重心的另一个定义。

那么假如我们已经获得了一个重心子树内的点 \(v\),我们只需要不断令\(v ← fa_v\),直到 \(2szv \ge sz1\) 即可找到重心,这个过程我们可以用树状数组/线段

树维护子树的点权和,配合倍增做到 \(O(log^2 n)\)

那么我们怎么找到 \(v\) 呢?考虑把点按 dfs 序排列为 \(p_i\),那么一个点的子树

对应这个排列的一个连续段,所以我们找到最小的 \(v\),使得 \(dp_i \ge sz_1\)

这个 \(v\) 一定在重心的子树内。我们二分查找到这个 \(v\) 即可。

总复杂度 \(O(q log^2n + n)\)

CF1667E

题面

对于所有点数为 \(n\) 的树,如果其满足对于所有 \(i \in [2, n]\),与\(i\)相连的\(j\)中恰有一个点 \(j\) 满足 \(j < i\) ,那么我们称其为好树。

\(\forall 1 \le i \le n\),求出来有多少好树满足重心为 \(i\)

重心定义满足为删去该点后形成的所有连通块大小均小于 \(\frac {n−1}{2}\) 的点。

数据范围 \(3 \le n \le 2 \times 105\)\(n\) 为奇数。

思路

\(f_i\) 为以 \(i\) 为根的子树大小超过 \(m =\frac{n+1}{2}\)的方案。

那么有:$$f_i=\sum_{j=m}^{n} \binom{n-i}{j-1}(i − 1)(n − j − 1)!(j − 1)! $$

其中 \(\binom{n-i}{j-1} (j-1)!\)为选择 \(j − 1\) 个点挂在 \(i\) 的子树内的方案,\((n − j − 1)!\) 为子树外的点选父亲的方

案,\(i − 1\) 为 $ i$ 选父亲的方案。

\[f_i=(n-i)!(i-1)\sum_{j=m}^{n}\frac{(n − j − 1)!}{(n − i − j + 1)!} \]

\[=(n-i)!(i-1)!\sum_{j=m}^{n}\binom{n-j-1}{i-2} \]

\[=(n-i)!(i-1)!\sum_{j=i-2}^{n-m-1}\binom{j}{i-2} \]

\[=(n-i)!(i-1)!\binom{n-m}{i-1} \]

考虑设 \(g_i\)\(i\) 为重心的方案数。考虑某个点 \(j(j > i)\) 向父亲跳的过程,那么 \(i\)\(j\) 的祖先的概率为 \(\frac{1}{i}\)

那么有:$$g_i=f_i\frac {\sum_{j=i+1}^{n}g_j}{i}$$

复杂度\(O(n)\)

相关题目

CF1707C

[NOIP2013 提高组] 货车运输

CF980E

CF1060E

CF1499F

谢谢大家!撒花~~~

posted @ 2023-07-28 15:30  Kylin_ZHH  阅读(76)  评论(0)    收藏  举报