无向图最小割 stoer_wagner算法

 1 const int  MAX_N = 1;
 2 int G[MAX_N][MAX_N];
 3 int v[MAX_N];            //    v[i]代表节点i合并到的顶点
 4 int w[MAX_N];            //    定义w(A,x) = ∑w(v[i],x),v[i]∈A
 5 bool visited[MAX_N];    //    用来标记是否该点加入了A集合
 6 
 7 int stoer_wagner(int n)
 8 {
 9     int min_cut = inf;
10     for (int i = 0; i < n; ++i)
11     {
12         v[i] = i;        //    初始还未合并,都代表节点本身
13     }
14 
15     while (n > 1)
16     {
17         int pre = 0;    //    pre用来表示之前加入A集合的点(在t之前一个加进去的点)
18         memset(visited, 0, sizeof(visited));
19         memset(w, 0, sizeof(w));
20         for (int i = 1; i < n; ++i)
21         {
22             int k = -1;
23             for (int j = 1; j < n; ++j)  //    选取V-A中的w(A,x)最大的点x加入集合
24             {
25                 if (!visited[v[j]])
26                 {
27                     w[v[j]] += G[v[pre]][v[j]];
28                     if (k == -1 || w[v[k]] < w[v[j]])
29                     {
30                         k = j;
31                     }
32                 }
33             }
34 
35             visited[v[k]] = true;        //    标记该点x已经加入A集合
36             if (i == n - 1)                //    若|A|=|V|(所有点都加入了A),结束
37             {
38                 const int s = v[pre], t = v[k];        //    令倒数第二个加入A的点(v[pre])为s,最后一个加入A的点(v[k])为t
39                 min_cut = min(min_cut, w[t]);        //    则s-t最小割为w(A,t),用其更新min_cut
40                 for (int j = 0; j < n; ++j)            //    Contract(s, t)
41                 {
42                     G[s][v[j]] += G[v[j]][t];
43                     G[v[j]][s] += G[v[j]][t];
44                 }
45                 v[k] = v[--n];                        //    删除最后一个点(即删除t,也即将t合并到s)
46             }
47             // else 继续
48             pre = k;
49         }
50     }
51     return min_cut;
52 }

 

posted @ 2017-04-03 17:11  Flowersea  阅读(302)  评论(0编辑  收藏  举报