最小割树

算法

最小割树是一个用于快速求无向图上任意两点间最小割的算法,它的定义如下:

称树 T T T 为 无向图 G G G 的最小割树,当且仅当 T T T 的节点与 G G G 一一对应,且对于所有边 ( u , v ) ∈ T (u,v) \in T (u,v)T,其边权为原图中 u , v u,v u,v 两点间最小割,同时满足在 T T T 中去掉这条边后剩下的两个不连通点集恰好为原图中 u , v u,v u,v 的最小割将原图分为的两个点集。

显然,我们可以直接根据定义递归建树,并利用最小割最大流定理每次跑一边网络流,代码:

void build(int l,int r){
   //node[l]到node[r]为当前要处理的连通点集
	if(l == r) return;
	int u = node[l],v = node[l + 1];//任选两点
	add(u,v,Max_Flow:: Dinic(u,v));
	int t1 = l - 1,t2 = r + 1;
	for(int i = l; i <= r; i ++){
   
		if(Max_Flow:: d[node[i]] == -1) t[--t2] = node[i];
		else t[++t1] = node[i];
		//d为Dinic的bfs中的到达数组,显然此时d中存的是最后一次bfs时的残量网络的连通情况
		//因为现在残量网络上s到达不了t,所以bfs访问到的点就是s所在的点集,它们的d不为0
	}
	for(int i = l; i <= r; i ++) node[i] = t[i];
	build(l,t1),build(t2,r);//node[l]到node[t1]为u所在点集,node[t2]~node[r]为v所在点集
}

那建出树后怎么查询呢?最小割树有一个重要的性质:

对于原图中任意两点 u , v u,v u,v,其最小割等于树上两点路径上边权的最小值

所以直接倍增维护就可以了。

证明

其正确性证明可以去看这篇博客,写的很严谨。

关于时间复杂度

严格来说,其时间复杂度上界约为 O ( n 3 m ) \Omicron(n^3m) O(n3m)(共跑 n − 1 n -1 n

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值