首页 > 代码库 > POJ2914 Minimum Cut 最小割集

POJ2914 Minimum Cut 最小割集

        题目大意是,给定N个顶点,M条边,两个顶点之间可能有多条边,求至少删除多少条边才能将该图分成两个子图。

        最小割集,典型的算法Stoer-Wagner,就是那篇论文,这里也就不复制过来了,只是用Prim求最大生成树时,更新的“边”不是普通意义上的边,而是顶点到所有已划分集合中的所有点的边权值和,这里要特别注意~ 直接贴代码~

#include <stdio.h>
#include <vector>
#include <math.h>
#include <string.h>
#include <string>
#include <iostream>
#include <queue>
#include <list>
#include <algorithm>
#include <stack>
#include <map>
#include <time.h>
using namespace std;
int G[501][501];

bool Visited[501];
int D[501];
int Edge[501];

int main()
{
#ifdef _DEBUG
	freopen("e:\\in.txt", "r", stdin);
#endif
	int n, m;
	while (scanf("%d %d", &n, &m) != EOF)
	{
		//memset(OriG, 0, sizeof(OriG));
		
		
		for (int i = 0; i < m; i++)
		{
			int s, t, v;
			scanf("%d %d %d", &s, &t, &v);
			G[s][t] += v; 
			G[t][s] += v;
		}
		int minans = 1000000000;
		int s = 0;
		int v = -1;
		Edge[0] = 0;
		for (int c = 0; c < n - 1;c++)
		{
			memset(Visited, 0, sizeof(Visited));
			memset(D, 0, sizeof(D));
		//	s = Edge[s];
			s = 0;
			Visited[s] = true;
			D[s] = 0;
			while (true)
			{
				int minedge = 0;
				v = -1;
				for (int i = 0; i < n; i++)
				{
					if (!Visited[i] /*&& G[s][i] > D[i]*/)
					{
						D[i] += G[s][i];
						
					}
					if (!Visited[i] && D[i] > minedge)
					{
						minedge = D[i];
						v = i;
					}
				}
				if (v == -1)
				{
					break;
				}
				Edge[v] = s;
				s = v;
				Visited[s] = true;
			}
			int total = 0;
			for (int i = 0; i < n; i++)
			{
				total += G[s][i];
			}
			if (total < minans)
			{
				minans = total;
			}
			G[s][Edge[s]] = 0;
			G[Edge[s]][s] = 0;
			for (int i = 0; i < n; i++)
			{
				G[Edge[s]][i] += G[s][i];
				G[i][Edge[s]] += G[i][s];
				G[i][s] = 0;
				G[s][i] = 0;
			}
		}
	
		printf("%d\n", minans);
	}
	return 0;
}