poj 2914 最小割 Stoer-Wagner 算法

来源:互联网 发布:在淘宝卖情趣用品 编辑:程序博客网 时间:2024/05/16 14:30
POJ - 2914点我点我
Minimum Cut
Time Limit: 10000MS Memory Limit: 65536KB 64bit IO Format: %lld & %llu

SubmitStatus

Description

Given an undirected graph, in which two vertices can be connected by multiple edges, what is the size of the minimum cut of the graph? i.e. how many edges must be removed at least to disconnect the graph into two subgraphs?

Input

Input contains multiple test cases. Each test case starts with two integers N and M (2 ≤ N ≤ 500, 0 ≤ MN × (N − 1) ⁄ 2) in one line, whereN is the number of vertices. Following areM lines, each line containsM integersA,B andC (0 ≤ A, B <N, AB, C > 0), meaning that thereC edges connecting verticesA andB.

Output

There is only one line for each test case, which contains the size of the minimum cut of the graph. If the graph is disconnected, print 0.

Sample Input

3 30 1 11 2 12 0 14 30 1 11 2 12 3 18 140 1 10 2 10 3 11 2 11 3 12 3 14 5 14 6 14 7 15 6 15 7 16 7 14 0 17 3 1

Sample Output

212


题意:给出n个点,m条无向边的图,要求删除总边权最小的一个边集,使图不连通,即最小割问题


题解:Stoer-Wagner 算法

      有一个定理:最小割等于最大流。

     不过本题不能用最大流的算法,不然会TLE,学习了下Stoer-Wagner 算法,代码不长,理解上稍稍难一些,算法过程如下:

     

     0.设ans = INF

     1.把所有的点加入, 选取任意一个点作为标准点,把其他的点的dis[]赋值成标准点与它本身的距离,并找离它最大的dis对应的点p.

     2.用p更新其他的未处理过的所有的点的dis[],把它们的dis[]加上它们与p的距离,并再次找到新的p(已经处理过的点不再算入),并重复2过程,直到把点处理完。

     3.然后把2过程的最后两个点之间的dis[]值用于更新答案,并且把这两个点缩成一个点,缩好点后,再更新图,假设要缩u,v变成v,  把所有到v边权加上u,v之间的边权,再返回第1步,直到缩得只剩下一个点


模拟:(http://blog.sina.com.cn/s/blog_700906660100v7vb.html)

 

poj 2914代码

#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>using namespace std;#define MAXN (500+5)#define INF 0x3f3f3f3f#define Set(a, v) memset(a, v, sizeof(a))#define For(i, a, b) for(int i = (a); i <= (int)(b); i++)int n, m;int G[MAXN][MAXN], v[MAXN], dis[MAXN];bool vis[MAXN];int stoer_wagner(){For(i, 1, n) v[i] = i;int ret = INF;while(n > 1){int p = 0, last = 0;For(i, 2, n){dis[v[i]] = G[v[1]][v[i]];if(dis[v[i]] > dis[v[p]]) p = i;}For(i, 2, n) vis[v[i]] = false;vis[v[1]] = true;For(i, 2, n){if(i == n){ret = min(ret, dis[v[p]]);For(j, 1, n) G[v[j]][v[last]] = G[v[last]][v[j]] += G[v[j]][v[p]];v[p] = v[n--];}vis[v[last=p]] = true; p = 0;For(j, 2, n)  if(!vis[v[j]]) {      dis[v[j]] += G[v[last]][v[j]];//更新dis      if(!p || dis[v[p]] < dis[v[j]]) p = j;   }}}return ret;}int main(){while(scanf("%d%d", &n, &m) != EOF){Set(G, 0);For(i, 1, m){int u, v, dis;scanf("%d%d%d", &u, &v, &dis);++u, ++v;G[u][v] += dis; G[v][u] += dis;}printf("%d\n", stoer_wagner());}return 0;}


  


2 0
原创粉丝点击