严格次小生成树学习笔记

前言

严格次小生成树,顾名思义,就是在联通图上选择一些边构成一棵树,使这棵树边权和严格次小。


第一步:求出最小生成树

要求严格次小生成树,我们就要先求出最小生成树 P r i m Prim Prim K r u s k a l Kruskal Kruskal等算法都可以,我用的是 K r u s k a l Kruskal Kruskal),在求最小生成树的过程中,还要给每条使用过的边打一个标记,代码如下:

inline void Kruskal()//求最小生成树
{
   
	register int res=0,tot=1;//res记录最小生成树的边权和,tot记录已经在树上的点数
	for(sort(e+1,e+m+1,cmp),i=1;i<=m&&tot<n;++i)//先将边按权值排序,只要已经在树上的点数小于n,就不断枚举下一条边
    {
   
        static LL fx,fy;
        if((fx=getfa(e[i].from))^(fy=getfa(e[i].to))) f[fy]=fx,res+=e[i].val,++tot,e[i].used=1,v[e[i].from].push_back(i),v[e[i].to].push_back(i);//合并两个联通快,更新res和tot,并标记这条边已使用
    }	
}

最小生成树的主要思想

讲如何求严格次小生成树之前,还要先回顾一下最小生成树的主要思想。

比如说 K r u s k a l Kruskal Kruskal,它的思想就是,贪心每次选择权值最小的一条边,判断这条边两边的点是否在同一个联通块内,也就是判断加上这条边之后是否会构成环


从最小生成树的主要思想而引发得到的思路

首先,我们应该有一个比较显然的想法:如果我们要求出严格次小生成树,那么肯定就是用一条边去替换最小生成树上的一条边。

现在假设我们已经选好了一条边(这可以拿来枚举),那么应该替换掉那一条边呢?

添上一条边肯定会使原来的树上形成一个环,要让这棵树重新变回树,那么显然要删掉这个环上的一条边,而无论删掉环上的哪一条边,结果都是一棵树。

既然删哪条边都无所谓,那么由于贪心的思想,显然是尽量删掉边权较大的边。

又因为我们是求严格次小生成树,因此,只要删掉边权严格小于新加上的那条边的边权边权最大的一条边。


如何确定这条边——倍增 L C A LCA LCA

现在我们已经知道应该删掉的边是什么样的了,但是如何确定这条边到底是哪条边呢?

我们可以假设新加上的这条边的左右端点分别为 u u u v v v,那么,要删掉的边必然位于最小生成树上 u u u v v v的路径之间。也就是肯定位于 u u u l c a ( u , v ) lca(u,v) lca(u,v) v v v l c a ( u , v ) lca(u,v) lca(u,v)的其中一条路径上。

那么我们就可以考虑倍增 L C A LCA LCA

L i n k Link L
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值