Stoer_Wagner算法解决无向图的最小割问题,其思想是:最小割可以把一张联通图分成两部分,对于图中任意两点,要么同时属于这两部分中的一部分,要么分别在这个两个集合中,我们枚举任意两点间的最小割,假如两点属于同一个集合,那么合并他们,因为不影响最终结果,然后继续,并一直更新 minCut ,直到遍历完毕。当然,这个复杂度嘛,相当销魂的……
具体流程网上很多,我也看了很多,推荐个吧,来自 小伟 ,个人感觉挺有帮助的:
然后是一个模板,来自 路竹 ,orz个先……
#include<cstdio>
#include<cstring>
#include<climits>
const int N = 501;
int n,mat[N][N],del[N],vis[N],dist[N];
int S,T;
int search(int tn){//T表征最后一个扩展进最大生成树的点,S是倒数第二个
int i,j,tmp,max,cut;
T=S=-1;
memset(vis,0,sizeof(vis));
memset(dist,0,sizeof(dist));//最大生成树
for(i=0;i<=n-tn;i++){
max=-1;
for(j=0;j<n;j++){
if(!vis[j] && !del[j] && dist[j]>max)
max=dist[j], tmp=j;
}
S=T; T=tmp;
cut=max;
vis[T]=1;
for(j=0;j<n;j++){
if(!vis[j] && !del[j])
dist[j]+=mat[T][j];
}
}
return cut;
}
int Stoer_Wagner(){
int ans=INT_MAX;
memset(del,0,sizeof(del));
for(int i=1;i<n;i++){//i 表征搜索次数,i越大图中剩余的点越少,自然搜索次数越少
int cut=search(i);
if(cut<ans)ans=cut;
if(ans==0)return 0;//图不连通时最小割为0
del[T]=1;
for(int j=0;j<n;j++){//S,T合并
if(!del[j])mat[S][j]=mat[j][S]+=mat[T][j];
}
}
return ans;
}
int main()
{
int a,b,c,m;
while(~scanf("%d%d",&n,&m))
{
memset(mat,0,sizeof(mat));
while(m--){
scanf("%d%d%d",&a,&b,&c);
mat[a][b]=mat[b][a]+=c;
}
int ans=Stoer_Wagner();
printf("%d\n",ans);
}
return 0;
}