Kruskal重构树学习笔记

Kruskal重构树前几天做noi2018的同步赛时,Day1T1我就拿了离线+树剖的80分暴力。 后来就知道有Kruskal重构树这样一种新科技(14年以前就有了)什么是Kruskal重构树简单来讲,就是在Kruskal算法进行的过程中,我们把最小生成树的边权改为点权。 这样,原树的节点个数变成2n-1个,并且有着许多有趣的性质。Kruskal重构树的性质1.根据我们构造...
摘要由CSDN通过智能技术生成

Kruskal重构树

前几天做noi2018的同步赛时,Day1T1我就拿了离线+树剖的80分暴力。
后来就知道有Kruskal重构树这样一种新科技(14年以前就有了)

什么是Kruskal重构树

简单来讲,就是在Kruskal算法进行的过程中,我们把最小生成树的边权改为点权。
这样,原树的节点个数变成2n-1个,并且有着许多有趣的性质。

Kruskal重构树的性质

1.根据我们构造的过程,这是一个二叉堆(后面再讲构造)
2.原树两点之间的边权最大值是重构树上两点Lca的权值
3.重构树中代表原树中的点的节点全是叶子节点,其余节点都代表了一条边的边权。
有了这些个性质,我们就可以解决一些问题了。

Kruskal重构树的构造

相信大家都会Kruskal
由于重构树中把原树的点权转换成为了新建节点的边权,这一过程是这样实现的。
首先对边排序
然后使用并查集辅助加边,每新建一条边时:
新建节点 index i n d e x (编号从 n+1 n + 1 开始)
将原有两节点所在集合改为 index i n d e x
将原有节点与 index i n d e x 连边
新建节点的权值为当前边的边权
给一下简单的代码

void Ex_Kruskal() {
    int ind=n,lim=n<<1; sort(e+1,e+1+m);
    for(int i=1;i<=lim;++i) f[i]=i;
    for(int i=1;i<=m;++i) {
        int fx=getfa(e[i].a),fy=getfa(e[i].b);
        if(fx!=fy) {
            f[fx]=f[fy]=++ind;
            val[ind]=e[i].w;
            add(ind,fx); add(ind,fy);
            if(ind==lim-1) break;
        }
    } return ;
}

代码复杂度很低,时间复杂度是优秀的

  • 25
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值