/*
translation:
给出一副无源汇的无向图,求其最小割。
solution:
原本的想法是枚举源汇,然后DINIC最大流。然而这样必然超时。所以必须有一种办法能够快速求出
全局最小割,这种算法就是stoer-wagner算法。具体方法见链接:http://blog.sina.com.cn
/s/blog_64018c2501011dd7.html以及http://blog.sina.com.cn/s/blog_7009066601
00v7vb.html。
note:
date:
2017.1.30
*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 500 + 5;
const int INF = 0x3f3f3f3f;
int wage[maxn], n, m;
bool in_set[maxn], vis[maxn];
int G[maxn][maxn];
int find_min_cut(int& S, int& T)
{
memset(wage, 0, sizeof(wage));
memset(vis, 0, sizeof(vis));
S = T = -1;
int min_cut, u = 0;
for(int i = 0; i < n; i++) {
int mx = -INF;
for(int j = 0; j < n; j++) {
if(!in_set[j] && !vis[j] && mx < wage[j]) {
mx = wage[j];
u = j;
}
}
if(u == T) return min_cut;
S = T; T = u;
min_cut = mx;
vis[u] = true;
for(int v = 0; v < n; v++) {
if(!in_set[v] && !vis[v]) {
wage[v] += G[u][v];
}
}
}
return min_cut;
}
int stoer_wagner()
{
int S, T;
int ans = INF, min_cut;
for(int i = 1; i < n; i++) {
min_cut = find_min_cut(S, T);
ans = min(ans, min_cut);
if(ans == 0) return ans;
in_set[T] = true;
for(int j = 0; j < n; j++) {
if(!in_set[j] && j != S) {
G[S][j] += G[T][j];
G[j][S] += G[j][T]; //缩点操作,将T节点的信息附加到S上面
}
}
}
return ans;
}
int main()
{
//freopen("in.txt", "r", stdin);
while(~scanf("%d%d", &n, &m)) {
memset(in_set, 0, sizeof(in_set));
memset(G, 0, sizeof(G));
int u, v, c;
for(int i = 0; i < m; i++) {
scanf("%d%d%d", &u, &v, &c);
G[u][v] += c;
G[v][u] += c;
}
printf("%d\n", stoer_wagner());
}
return 0;
}
poj2914(stoer-wagner算法求解全局最小割)
最新推荐文章于 2019-12-04 22:49:00 发布