kruskal重构树
克鲁斯卡尔重构树
应用
- 区间点可相互到达时考虑
- 连通块题目考虑
- 用到的边是“连通块内的最小生成树”时考虑
性质
- 所有原节点都为叶子节点
- 有
2*n-1个节点,叶子是点权,非叶子是边权 - 任何两个叶子节点可以相互到达,
一定是通过了他们的LCA所代表的那条边到达的。 - 重构树一定是小根堆或者大根堆(针对于点的id,针对于点的“边权”)
- 选出一些点可以互相到达,且最大边权不可以超过x,则答案是
非叶节点中点权大于等于x的所有子树中的点
注意(性质)
- 重构树中的
非叶子点权不一定都不相同,但是根的点权一定最大 - 重构树一定是
堆 - 在重构树上若到达某个
非叶子节点 x,则x子树的所有叶子节点,都可以相互到达。 - 重构树中,若一个区间的点可以相互到达,求需要经过的边权的
最小值?答案为max{LCA(L,L+1),LCA(L+1,L+2),…,LCA(R-2,R-1)},此时可以用线段树维护区间最大值解决多组询问
对于4的证明:
设4中求出的答案为t,则L和L+1可以相互到达,L+1和L+2可以相互到达…,所以任意两个点都可以相互到达。
题目
E. Qpwoeirut and Vertices
题意
给我们一个无向无权图(n个点,m条边,边有编号),若干个询问(q组),每次询问给我们一个区间[ l , r ] ,问我们只经过前k条边使得该区间内任意两点可以互相到达的k的最小值。
思路
- 将边的id看成边权,建立重构树
- 预处理lca数组
- 对于区间[l,r]内,若这个区间的点可以相互到达,只需要求出LCA(l,l+1,…r-1)的点权即可
代码
1 | |
注意区间右端点
2021ICPC上海站Life is a Game
题意
给我们一个无向有权图。
点有点权,边有边权。。我们可以在图上来回走,走到一个点后会获得该点的价值,能够重复到达一个点但是不能重复获得该点的价值。但是,从一个点走到另一个点需要满足当前带有的价值要大于边权。
若干次询问,每次询问给一个起点和一个价值,问最多可以获得多少价值。
思路
- 考虑到可以在一个连通块内随意走,而且走的边一定是这个连通块的“最小生成树边”,所以正好符合重构树
- 建立重构树之后,如果可以到达某个
非叶子节点x,那么x的子树的叶子节点的权值都可以被收集到 - 考虑假设到达了某
非叶子节点x,是否可以向上走,只需要此时的价值>父亲节点的点权即可
代码
1 | |
注意:dd数组表示至少需要k才可以跳,那么如果最开始在x位置额外拥有k,无论跳到哪里,都额外拥有k,k不会变化