POJ 2914 无向图最小割

以前总结过无向图最小割的最大流算法,n^2的枚举起点和终点,这个题必然tle

于是又学习了专门的算法:Stoer-Wagner算法

 

就是利用prim求最大生成树,将最后扫到的两点合并,执行n-1次,最终合并成一个点

参考资料:

http://kanboxshare.com/link/gCrQIYPJvdwCxGlOUwU5U3yxNNIiW2cUxIhddx7T60uYmiiO2heSC1rULa5tjEbf3MLRsM8QRKYGzoZhd8abNaUke

 

View Code
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <algorithm>
 5 #include <iostream>
 6 
 7 #define N 600
 8 #define INF 1e9
 9 
10 using namespace std;
11 
12 int map[N][N],q[N],dis[N];
13 bool vis[N],cut[N];
14 int n,m,S,T;
15 
16 inline void read()
17 {
18     memset(map,0,sizeof map);
19     memset(cut,0,sizeof cut);
20     for(int i=1,a,b,c;i<=m;i++)
21     {
22         scanf("%d%d%d",&a,&b,&c);
23         map[a][b]+=c; map[b][a]+=c;
24     }
25 }
26 //Stoer-Wagner算法
27 //prim求出最大生成树,将最后扫到的两点合并,执行n-1次 
28 inline int mincut(int now) 
29 {
30     int tot=0;
31     memset(vis,0,sizeof vis);
32     memset(dis,0,sizeof dis);
33     for(int j=0,tmp,k;j<now;j++)
34     {
35         tmp=-INF;
36         for(int i=0;i<n;i++)
37             if(!cut[i]&&!vis[i]&&tmp<dis[i]) tmp=dis[i],k=i;
38         q[++tot]=k; vis[k]=true;
39         for(int i=0;i<n;i++)
40             if(!cut[i]&&!vis[i]) dis[i]+=map[k][i];
41     }
42     S=q[tot-1]; T=q[tot];
43     return dis[T];
44 }
45 
46 inline void contract()
47 {
48     map[S][T]=map[T][S]=0;
49     cut[T]=true;
50     for(int i=0;i<n;i++)
51         if(i!=S&&!cut[i]) map[i][S]=map[S][i]=map[S][i]+map[T][i];
52 }
53 
54 inline void go()
55 {
56     int ans=INF;
57     for(int i=n;i>1;i--)
58     {
59         ans=min(ans,mincut(i));
60         contract();
61     }
62     printf("%d\n",ans);
63 }
64 
65 int main()
66 {
67     while(scanf("%d%d",&n,&m)!=EOF) read(),go();
68     return 0;
69 }

 

 

posted @ 2013-01-08 00:01  proverbs  阅读(578)  评论(0编辑  收藏  举报