Nubulsa Expo (全局最小割)

一、前言

全局最小割板题。

二、题目

Vjudge

求给定源点的无向图最小割。

三、讲解

(一)、科技:全局最小割

首先我们有个连我都能感性理解的算法:任选两个点,求出最小割并更新答案,合并这两个点,最后求出的答案即为全局最小割。这其实就是并不出名大名鼎鼎的 Stoer-Wagner算法。

由于是任选两个点求最小割,所以我们其实有比跑网络流更快的做法:

我们搞一个点集 A,初始里面随便放个点,每次选择 dis(A,u)=aAdis(a,u) 最大的点加入点集。

设第 i 次加入的点是 ui,那么 cutun1,un 割开的点集为 {u1,u2,...,un1},{un}

所以做一次上述做法就可以得到随机两个点的最小割,做 n1 次就可以得到全局最小割。

这个过程可以用类似 Prim 或者说无堆优化的 dijkstra 的方式实现,时间复杂度是 O(n3) 的,如果用堆优化,复杂度是 O(nmlog2n) 的。

证明啥的可以去看集训队论文。

(二)、正题

之所以叫正题是因为这篇博客本应是题解。

我们可以注意到这个源点其实没啥用,我们要求的就是全局最小割,证明的话你就考虑全局最小割会把源点 S 割到一边,在另一边随便选个点其实就是题目所求给定源点的最小割。

知道这个就可以直接上板子了。

我用的是 O(n3) 的做法。

四、代码

//12252024832524
#include <bits/stdc++.h>
#define TT template<typename T>
using namespace std; 

typedef long long LL;
const int MAXN = 305;
const int MAXM = 50005;
const LL INF = 1ll << 60;
int n,m;

LL Read()
{
	LL x = 0,f = 1;char c = getchar();
	while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
	return x * f;
}
TT void Put1(T x)
{
	if(x > 9) Put1(x/10);
	putchar(x%10^48);
}
TT void Put(T x,char c = -1)
{
	if(x < 0) putchar('-'),x = -x;
	Put1(x); if(c >= 0) putchar(c);
}
TT T Max(T x,T y){return x > y ? x : y;}
TT T Min(T x,T y){return x < y ? x : y;}
TT T Abs(T x){return x < 0 ? -x : x;}

bool vis[MAXN],vis2[MAXN];
LL e[MAXN][MAXN],dis[MAXN];
void Add_Double_Edge(int u,int v,int w){
	e[u][v] += w;
	e[v][u] += w;
}

int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	while(1){
		LL ans = INF;
		n = Read(); m = Read(); Read(); 
		if(!n && !m) return 0;
		for(int i = 1;i <= n;++ i) vis[i] = 0;
		for(int i = 1;i <= n;++ i) for(int j = 1;j <= n;++ j) e[i][j] = 0;
		for(int i = 1,u,v;i <= m;++ i) u = Read(),v = Read(),Add_Double_Edge(u,v,Read());
		for(int cas = 1;cas < n;++ cas){//contract 
			int now = 0,lst = 0,cnt = 0;
			for(int i = 1;i <= n;++ i){//begin
				if(!vis[i]) now = i,++cnt;
				dis[i] = 0;
			}
			for(int i = 1;i <= n;++ i) if(!vis[i]) dis[i] = e[now][i],vis2[i] = 0;
			vis2[now] = 1;
			for(int i = 1;i < cnt;++ i){
				lst = now; dis[now] = -1;
				for(int j = 1;j <= n;++ j) if(!vis2[j] && dis[j] > dis[now]) now = j;
				vis2[now] = 1;
				for(int j = 1;j <= n;++ j) if(!vis2[j]) dis[j] += e[now][j];
			}
			ans = Min(ans,dis[now]); vis[now] = 1;
			for(int i = 1;i <= n;++ i) e[lst][i] += e[now][i],e[i][lst] += e[i][now];
		}
		Put(ans,'\n');
	}
	return 0;
}
posted @   皮皮刘  阅读(58)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
点击右上角即可分享
微信分享提示