「学习笔记」Kruskal重构树

首先要知道一种叫做克鲁斯卡尔求最值生成树的东西

在实现 (Kruskal) 算法的时候,进行并查集操作的时候,要注意到要合并两个子树

这时候我们可以像线段树的 (push\_up) 一样来维护一些量,比如权值等等

构建的时候就是在并查集的合并新建一个节点,然后把点的权值记录成要维护的极值,所以如果查询图上的类似信息,可以考虑 (LCA)

或者以下问题

“经过图上不超过一个给定值能达到的最远的边”

(画一棵树模拟一下你就知道咋做了)

”两个点之间经过路径最长边的最小值“(bzoj3732)

(好像是最小生成树完了 (LCA)

都是可以考虑用这个算法解决的

但是解决的问题的范围还是有限,最多是一些”最大最小“同时出现的,或者离线可二分的东西


建出来的生成树有一些性质:

(1.) 因为克鲁斯卡尔,所以每个点到根经过路径上的点权是单调的

(2.) 树上除了叶子节点是一一对应原来图上的点之外,别的所有点是对应树上的边

(3.) 克鲁斯卡尔重构树是棵二叉树

(4.) 如上面的解决的问题所说,图上面任意两个节点某种权值的瓶颈就在它们的 (lca)

Description

link

题面细节相对多,建议去链接中阅读

Solution

首先发现这里限制了一个维度(海拔)

就是先按照海拔从大到小排个序,扔到重构树里面

这里的重构树是一个小根堆,如果走到小于海拔限制的就不能走了

每次查询,直接从重构树上面往上走,走到那个超过海拔限制的点结束

这部分需要树上倍增

然后该点的子树里面的所有点都是可以直接坐车到的

然后考虑的就是找到这些点里面到 (1) 距离的最小值

直接 (dfs) 解决掉就好了

还是一道运用性质的不错的题目

就像 (NOI2013) 是删掉基环树上一条边后求直径的最小值一样

代码慢慢打吧


然后是下一道例题:

IOI2018狼人

其实相对而言比较好说

首先克鲁斯卡尔重构树维护可以走到的点,建一个大根的,一个小根的

然后在以两个点为根的子树里面求交集

如果有交集,那么就是 (1)

否则就是 (0)

树的子树求交集问题?

先求出来 (dfs) 序,然后以 (d_A) 为下标,(d_B) 为权值建主席树

然后查询的本质就是跳 (father) 和二维数点

原文地址:https://www.cnblogs.com/yspm/p/13466089.html