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;//圖不連通時最小割為0del[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;}