模板:
void kruskal(){
for(int i=1;i<=n;i++)fa[i]=i;
nd=n;
sort(e+1,e+m+1,cmp);
for(int i=1;i<=m;i++){
int fx=find(e[i].x);
int fy=find(e[i].y);
if(fx==fy)continue;
val[++nd]=e[i].v;
fa[fx]=fa[fy]=fa[nd]=nd;
add(fx,nd);add(nd,fx);
add(fy,nd);add(nd,fy);
}
for(int i=nd;i>=1;i--)
if(!dep[i])dfs(i,0);
return;
}
根据上述代码建出的重构树称为\(Kruskal\)重构树,
它满足以下性质:
- 一棵二叉树
- 叶子结点都是原图中的点,没有点权;非叶子结点都是新加的点,有点权
- 最小\(Kruskal\)重构树是大根堆,最大\(Kruskal\)重构树是小根堆
- 旧点 \(u,v\) 两点的\(LCA\)(是新点)权值为原图中 \(u,v\) 两点间所有路径的最长边的最小值(最小生成树这样,最大的反之)
练习:
模板
最短路+\(Kurskal\)重构树
根据小根堆性质暴力倍增
主席树+\(Kurskal\)重构树