无向图最小割 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 }