Kruskal 重构树

感谢 Alex_Wei 的博客,让我受益匪浅。

回忆 Kruskal 算法的过程,按边权从小到大排序,若当前边 u,v 在当前图上还不连通,则加入该边,并查集维护这个过程。

Kruskal 重构树就是在加入 (u,v) 时,建立虚点 x,令点权 wx=w(u,v),建边 xiduxidv,并将 idu,idv 设为 x。这样得到一棵 2n1 个点的二叉树,初始的节点都是树上的叶子,且满足大根堆的性质。

一个应用是求出 u 只经过边权 x 的边最多可以到达多少个节点。因为 wfauwu,可在重构树上倍增,找到 u 深度最浅的祖先 f 满足 wfx,答案为 f 的子树内的叶子个数。

当问题变为点权的限制后,也可以用重构树解决。一种解决方法是将 w(u,v) 设为 max(wu,wv),然后用边权的方法做。

存在另一种不需要建虚点的建树方法。按点权从小到大排序,设当前考虑到点 i,遍历每条边 (i,u),若 u 已被考虑过即 wuwi,且 i,u 不连通,则建边 iidu。这样构造显然也满足大根堆的性质,但是它是一棵多叉树。

例题

CF1797F Li Hua and Path

求出满足一类限制,满足二类限制,满足一类和二类限制的答案 A,B,C,答案即为 A+B2C

考虑加入父亲为 x 的点 iA,B,C 的影响。B 增量显然是 i1AC 的增量相同,设 ci 表示有多少条路径 ui 满足 u 是路径上的最小值,A 增量就是 ci。考虑 ci 如何转移,因为若路径 ux 满足 u 是路径最小值,则 ui 一定也满足,再加上路径 xi,即 ci=cx+1。综上,每次增量为 i1ci

于是只需处理初始的 A,B,Cci 即可。建出小根堆和大根堆的点权多叉重构树 TminTmax。点 iA,B 的贡献是 i 分别在 TminTmaxsizi1,因为子树内的点都是可以满足 ii 的限制到达的。ci 就是 iTmin 上的深度。C 也就是统计有多少 x,y 满足 xTmin 上是 y 的祖先,yTmax 上是 x 的祖先,这个树状数组随便计算就好了。复杂度 O(nlogn)

P4768 [NOI2018] 归程

这个就是上述的经典应用。建出 Kruskal 重构树,找到第一个 f 满足 wf>S,在 f 的子树内找 disi 最小值即可。

posted @   Terac  阅读(31)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示