【学习笔记】kruskal 重构树
(本文章同步于洛谷博客)
写这篇博客主要是因为oi-wiki上写得太精简了……我对着这几段话弄了一晚上才搞明白/kk,因此决定根据自己的理解写一篇详尽的 kruskal 重构树的学习笔记,可以配合 oi-wiki 食用。
前置知识:最小生成树,与 kruskal 算法
kruskal重构树的构造
在进行 kruskal 算法时,我们会将当前边的两个端点
x
x
x 和
y
y
y 所在的树合并成一棵,即连一条由
x
x
x 的树根指向
y
y
y 的树根的边,写成代码就是f[xx]=yy(假设
x
x
xx
xx 和
y
y
yy
yy 分别为
x
x
x 和
y
y
y 对应的根结点)。而 kruskal 重构树则是在合并时引入一个新的结点
n
o
d
nod
nod,用
n
o
d
nod
nod 作为
x
x
xx
xx 和
y
y
yy
yy 的父亲,即f[xx]=nod,f[yy]=nod,同时将
x
x
x 和
y
y
y 之间的边的权值赋予新加的结点(叶节点的权值视为
0
0
0)。以这种方式得到的树就是 kruskal 重构树(以下简称“重构树”,如无特殊说明默认为最小生成树的重构树)。重构树无边权,有点权,每个非叶子结点都一一对应着最小生成树上的一条边。它具备一些比较优良的性质,因此能方便地解决一些问题。
重构树的性质
性质 1 1 1:若最小生成树有 n n n 个结点,那么重构树一定有且仅有 2 n − 1 2n-1 2n−1 个结点,其中有 n n n 个结点是叶子结点,并且叶子结点一定是原有的点,非叶子结点一定是新加的点。同时,非叶子结点一定有且仅有 2 2 2 个子结点。
好理解,由构造方式就能看出新加的点一定是 2 2 2 个结点的父亲,原有的点一定没有子结点。
性质 2 2 2:重构树上两个叶子结点 x x x 和 y y y 之间的路径上的点(不包含 x x x 和 y y y 本身)与最小生成树上 x x x 到 y y y 的路径上的边一一对应。
之前说过重构树上的每个非叶子结点都一一对应着最小生成树上的一条边,结合重构树的构造过程也好理解。
性质 3 3 3(重要):在重构树里,深度越浅的结点的权值一定越大
这其实就是 kruskal 重构树算法的精髓和妙处所在。由于我们在进行 kruskal 算法时是按边权从小到大选的,因此边权大的边一定更晚被选中,转换到重构树上就是深度更浅。
这样一来,重构树上的结点的深度就与重构树上的点权、最小生成树上的边权联系在了一起,你很快就会发现这是个多么好的性质。
性质 4.1 4.1 4.1:最小生成树上任意两点 x , y x,y x,y 之间的“瓶颈”的大小与重构树上 x , y x,y x,y 两点的最近公共祖先(lca)的点权相同。
“瓶颈”指的就是两点之间的路径所经过边的边权最大值,由性质 2 2 2 我们可以知道最小生成树上的这条路径对应到重构树上也是一条路径,又由于性质 3 3 3,深度越浅的结点权值越大,lca 是重构树的这条路径上最浅的那个结点,因此权值肯定是最大的,因此 lca 的点权就是最小生成树上两点的“瓶颈”大小。
性质 4.2 4.2 4.2:原图上任意两点 x , y x,y x,y 之间的最小“瓶颈”的大小与重构树上这两点的 lca 的点权相同
性质 4.1 4.1 4.1 的拓展,因为最小生成树同时也是最小瓶颈生成树。
性质 5 5 5:对于图上一点 x x x,满足与 x x x 的最小瓶颈的大小 ≤ v a l \le val ≤val 的所有点在重构树上是同一结点的子树里的所有叶子结点。
这个初看可能摸不着头脑,我们可以反着考虑一下,先尝试着找出这样的一个结点。如果 y y y 是重构树上 x x x 到根结点的路径上权值最大的满足权值 ≤ v a l \le val ≤val 的结点(也就是最浅的满足条件的点)。首先 x x x 肯定属于 y y y 子树内的叶结点。那么对于其他叶结点 z z z,如果 z z z 在 y y y 子树内, x x x 和 z z z 的 lca 的深度一定小于等于 y y y 的深度,由性质 3 3 3 和 4 4 4, x x x 和 z z z 之间的最小瓶颈的大小一定小于等于 v a l val val。反之亦然。
例题
kruskal 重构树的题目一般都和图上路径的最值(“瓶颈”)有关
-
[NOIP2013 提高组] 货车运输 妥妥的裸题,建出重构树后跑lca就行。
-
[NOI2018] 归程 比较暴力的想法是求出从这一点只乘车所能到达的结点,然后对这些点到 1 1 1 的最短路径取 m i n min min。我们发现这就等价于求所有与点 v v v 的最小瓶颈大小 ≤ p \le p ≤p 的点,由性质 5 5 5,这些点一定是重构树上某个结点 x x x 的所有叶结点。用Dijkstra求出 dis 数组,再把重构树建出来,通过 dfs 可以预处理出重构树上所有结点的叶结点的 dis 的最小值。那每次询问时只需要通过倍增求出 x x x。搞定

浙公网安备 33010602011771号