1. 程式人生 > >POJ 2914 Minimum Cut 最小割算法題解

POJ 2914 Minimum Cut 最小割算法題解

toe 最小 main pre 生成 12px trac style size

最標準的最小割算法應用題目。

核心思想就是縮邊:先縮小最大的邊。然後縮小次大的邊。依此縮小

基礎算法:Prime最小生成樹算法


只是本題測試的數據好像怪怪的,相同的算法時間執行會區別非常大,並且一樣的代碼替換。竟然會WA。系統出錯的幾率非常小。難倒測試系統本題會有錯誤?

懶得繼續測試這道題的系統了,反正算法正確。AC。

#include <stdio.h>
#include <string.h>
#include <limits.h>

const int MAX_N = 500;
int N, M, A, B, C, S, T;
int gra[MAX_N][MAX_N], dis[MAX_N];
bool vis[MAX_N], delVer[MAX_N];

inline int min(int a, int b) { return a < b ? a : b; }

int search(int V)	//V為計算剩下多少頂點了
{
	memset(vis, 0, sizeof(vis));
	memset(dis, 0, sizeof(dis));
	int curMax = 0, cur = 0;
	S = 0, T = 0;
	for (int i = 1; i < V; i++)
	{
		curMax = 0;
		for (int j = 1; j < N; j++)
		{
			if (!vis[j] && !delVer[j]) dis[j] += gra[cur][j];
		}

		for (int j = 1; j < N; j++)
		{
			if (!vis[j] && !delVer[j] && dis[j] > curMax)
			{
				curMax = dis[j];
				cur = j;
			}
		}
		vis[cur] = true;
		if (T == cur) return 0; //圖不相連。提前結束循環,割點為0
		S = T; T = cur;		//目的得到最後和倒數第二節點。以便進行縮圖
	}
	return curMax;
}

//核心思想:先縮小最大的邊,然後縮小次大的邊,依此縮小
int Stoer_Wagner()
{
	memset(delVer, 0, sizeof(delVer));
	int minCut = INT_MAX;
	for (int v = N; v > 1; v--) //共N-1條邊, 當前v個點
	{
		minCut = min(minCut, search(v));
		if (minCut == 0) return 0;	//一點優化,提前結束
		delVer[T] = true;
		for (int i = 0; i < N; i++)
			if (!delVer[i]) gra[S][i] = gra[i][S] += gra[T][i];
	}
	return minCut == INT_MAX ? 0 : minCut;//僅僅有一個頂點的時候返回0
}

int main()
{
	while (~scanf("%d %d", &N, &M))
	{
		memset(gra, 0, sizeof(gra));
		for (int i = 0; i < M; i++)
		{
			scanf("%d %d %d", &A, &B, &C);
			gra[B][A] = gra[A][B] += C;
		}
		printf("%d\n", Stoer_Wagner());
	}
	return 0;
}



POJ 2914 Minimum Cut 最小割算法題解