题解 P5632 【【模板】Stoer-Wagner算法】
Stoer-Wagner 全局最小割算法
之前一篇题解没有证明,我来加上一个证明。
参考文章:全局最小割StoerWagner算法详解 By Oyking
设原图为
算法基本思想:对于无向图上任意两点
- 对于
s,t 处于同一连通块的情况,根据割的定义,割去C 后至少有一个点j ,与s 不在一个连通块内,则j,t 也不在一个连通块内,那么j 与s,t 都不在一个连通块内,所以凡是j 与s,t 之间的边必须全部割去,如果(j,s) 边被割去,则如果(j,t) 未被割去,(j,s) 不割是一种更小的割法(与最小割矛盾),因此如果(j,s)\in C ,则有(j,t)\in C ,所以s,t 可看作是一个整体,共享所有的边。
那么,处理完一对
- 下面主要探讨
s,t 不在一联通块时的答案,即s,t 之间的最小割,注意s,t 的选择是任意的。
构造过程依赖于一个集合
加入顺序依赖于权值函数
算法流程:每次选择
下面来证明一下以上算法的正确性(来自最上面的链接):
若点
下证对于任意一个 Active 结点
运用数学归纳法,对于第一个 Active 结点
对于
#include <bits/stdc++.h>
using namespace std;
const int MAXN=610,INF=1e9;
int n,m,x,y,z,s,t,dis[MAXN][MAXN],w[MAXN],dap[MAXN],vis[MAXN],ord[MAXN];
int proc (int x) {
memset(vis,0,sizeof(vis));
memset(w,0,sizeof(w));
w[0]=-1;
for (int i=1;i<=n-x+1;i++) {
int mx=0;
for (int j=1;j<=n;j++) {
if (!dap[j]&&!vis[j]&&w[j]>w[mx]) {mx=j;}
}
vis[mx]=1,ord[i]=mx;
for (int j=1;j<=n;j++) {
if (!dap[j]&&!vis[j]) {w[j]+=dis[mx][j];}
}
}
s=ord[n-x],t=ord[n-x+1];
return w[t];
}
int sw () {
int res=INF;
for (int i=1;i<n;i++) {
res=min(res,proc(i));
dap[t]=1;
for (int j=1;j<=n;j++) {
dis[s][j]+=dis[t][j];
dis[j][s]+=dis[j][t];
}
}
return res;
}
int main () {
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++) {
scanf("%d%d%d",&x,&y,&z);
dis[x][y]+=z,dis[y][x]+=z;
}
printf("%d\n",sw());
return 0;
}