Minimum Cut POJ - 2914

传送门:QAQ

题意:就是让你求出图中的最小割

思路:模板题,使用Store-Wagner 算法能快速求出最小割

附上代码:

#include <iostream>  
#include <stdio.h>  
#include <string.h>  
#include <stack>  
#include <queue>  
#include <map>  
#include <set>  
#include <vector>  
#include <math.h>  
#include <bitset>  
#include <algorithm>  
#include <climits>  
using namespace std;
const int inf=0x3f3f3f3f;

typedef long long LL;
const int maxn = 5100;

int ax[maxn];
int bn[maxn];
int gx[510][510];
int dis[510];
int v[510];
int vis[510];
int Stoer_Wagner(int n)
{
	int i, j, res = inf;
	for (i = 0; i < n; i++)
		v[i] = i;////保存顶点 ,固定顶点为自己
	while (n > 1)
	{
		//pre用来表示之前加入A集合的点
		//我们每次都以0点为第一个加入A集合的点 
		int k = 1, pre = 0;
		for (i = 1; i < n; i++) {
			dis[v[i]] = gx[v[0]][v[i]];
			if (dis[v[i]] > dis[v[k]])
				k = i;
		}
		memset(vis, 0, sizeof(vis));
		vis[v[0]] = true;//标记该点已经加入A集合  
		for (i = 1; i < n; i++)
		{
			if (i == n - 1)//最后一次加入的点就要更新答案
			{
				res = min(res, dis[v[k]]);
				for (j = 0; j < n; j++) //将该点合并到pre上,相应的边权就要合并  
				{
					gx[v[pre]][v[j]] += gx[v[j]][v[k]];
					gx[v[j]][v[pre]] += gx[v[j]][v[k]];
				}
				v[k] = v[--n];//删除最后一个点
			}
			vis[v[k]] = true;
			pre = k;
			k = -1;
			for (j = 1; j < n; j++)
				if (!vis[v[j]])
				{
					//将上次求的 k 加入集合,合并与它相邻的边到割集 
					dis[v[j]] += gx[v[pre]][v[j]];
					if (k == -1 || dis[v[k]] < dis[v[j]])
						k = j;
				}
		}
	}
	return res;
}
int main(void) {
	int n, m;
	while (scanf("%d%d", &n, &m) != EOF) {
		memset(gx, 0, sizeof(gx));
		for (int i = 0; i < m; i++) {
			int a, b, c;
			scanf("%d%d%d", &a, &b, &c);
			gx[a][b] += c;
			gx[b][a] += c;
		}
		printf("%d\n", Stoer_Wagner(n));
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liexss/article/details/86562299