poj 2914 无向图全局最小割

对于无向图的s-t割,直接网络流即可。如果要求全局最小割,固定源点需要做n次网络流太慢。而StoerWagner算法可在O(n^3)时间内解决。

StoerWagner算法做n次类似prim求最大生成树的过程,每次求出两点(不确定)间的最小割,然后合并这两个点。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <cmath>
  6. using namespace std;
  7.  
  8. typedef long long ll;
  9. const int maxn=510, maxm=2010;
  10. #define INF 1e9
  11.  
  12. const int N=510;
  13.  
  14. int a[N][N];
  15.  
  16. int dis[N], node[N];
  17. bool vis[N];
  18. //O(V^3), and we can optimze to O(V(V+E)log(V))
  19. //a[0..n-1][0..n-1] is graph weight
  20. //dis[] indicates current cut size to close-list,
  21. // the prim-like algo insert max dis[] node into close-list 
  22. int StoerWangner(int n){
  23. 	for (int i=0;i<n;i++) node[i]=i;
  24. 	int ans=INF;
  25. 	while (n>1){ //iterations
  26. 		int maxx=1, prev=0;
  27. 		//prim-like algorithm
  28. 		memset(vis,0,sizeof vis);
  29. 		vis[node[0]]=1;
  30. 		for (int i=1;i<n;i++){ //first step of prim
  31. 			dis[node[i]]=a[node[0]][node[i]];
  32. 			if (dis[node[i]]>dis[node[maxx]])
  33. 				maxx=i;
  34. 		}
  35. 		for (int i=1;i<n;i++){
  36. 			if (i==n-1){ //iter end, merge s-t, here merge maxx to prev
  37. 				ans=min(ans, dis[node[maxx]]);
  38. 				for (int k=0;k<n;k++) //merge node without disjoint set
  39. 					a[node[k]][node[prev]]+=a[node[k]][node[maxx]],
  40. 					a[node[prev]][node[k]]+=a[node[k]][node[maxx]];
  41. 				node[maxx]=node[--n]; //delete maxx node
  42. 			}
  43. 			vis[node[maxx]]=1;
  44. 			prev=maxx;
  45. 			maxx=-1;
  46. 			for(int j=1;j<n;j++) if (!vis[node[j]]){
  47. 				dis[node[j]]+=a[node[prev]][node[j]]; //upd dis
  48. 				if (maxx==-1 || dis[node[j]]>dis[node[maxx]]) //upd maxx
  49. 					maxx=j;
  50. 			}
  51. 		}
  52. 	}
  53. 	return ans;
  54. }
  55.  
  56. //poj 2914
  57. int main(){
  58. 	int n,m;
  59. 	while (~scanf("%d%d",&n,&m)){
  60. 		memset(a,0,sizeof a);
  61. 		while(m--){
  62. 			int u,v,w;
  63. 			scanf("%d%d%d",&u,&v,&w);
  64. 			a[u][v]+=w;
  65. 			a[v][u]+=w;
  66. 		}
  67. 		printf("%d\n",StoerWangner(n));
  68. 	}
  69. 	return 0;
  70. }

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注