http://acm.hdu.edu.cn/showproblem.php?pid=3691
Stoer-Wagner算法 不理解不理解呀
大体步骤是这样子的
1,用类似Prim 的过程求得最后更新点 和倒数第二更新点
2,求最后更新点和其它点的割集
3,将最后一个点合并到倒数第二个更新点上
代码:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int INF=0x7fffffff; const int N=305; int a[N][N]; int dist[N]; bool visited[N],dele[N]; int n,m,st; int nd1,nd2; void Prim() { memset(dist,0,sizeof(dist)); for(int i=1;i<=n;++i) { if(!dele[i]) { dist[i]=a[st][i]; } } nd1=nd2=st; memset(visited,false,sizeof(visited)); visited[st]=true; for(int w=1;w<n;++w) { int M=0,k=0; for(int i=1;i<=n;++i) { if(!dele[i]&&!visited[i]&&dist[i]>M) { M=dist[i];k=i; } } if(k==0) break; visited[k]=true; for(int i=1;i<=n;++i) { if(!dele[i]&&!visited[i]) { dist[i]+=a[k][i];//这里好奇怪 } } nd2=nd1;//最后更新点 和倒数第二更新点 nd1=k; } return; } int Findmin() { int sum=0; for(int i=1;i<=n;++i) { if(!dele[i]) { sum+=a[nd1][i];//最后更新点的割集 } } return sum; } void Removepoint() { dele[nd1]=true; for(int i=1;i<=n;++i) { if(!dele[i]&&i!=nd2) { a[i][nd2]+=a[i][nd1];//合并最后更新点 a[nd2][i]+=a[nd1][i]; } } } int main() { while(scanf("%d %d %d",&n,&m,&st)!=EOF) { if(!n&&!m&&!st) break; memset(a,0,sizeof(a)); while(m--) { int i,j,k; scanf("%d %d %d",&i,&j,&k); a[i][j]+=k;//重边 a[j][i]+=k; } int ans=INF; memset(dele,false,sizeof(dele));//此点是否删除 for(int w=1;w<n;++w) { Prim(); ans=min(ans,Findmin()); Removepoint(); } printf("%d\n",ans); } return 0; }