Kuhn_Munkres最大權匹配算法C++模板

#include <cstdio>
#include <memory.h>
#include <algorithm> // 使用其中的 min 函數
using namespace std;

const int MAX = 1024;

int n; // X 的大小
int weight [MAX] [MAX]; // X 到 Y 的映射(權重)
int lx [MAX], ly [MAX]; // 標號
bool sx [MAX], sy [MAX]; // 是否被搜索過
int match [MAX]; // Y(i) 與 X(match [i]) 匹配

// 初始化權重
void init (int size);
// 從 X(u) 尋找增廣道路,找到則返回 true
bool path (int u);
// 參數 maxsum 爲 true ,返回最大權匹配,否則最小權匹配
int bestmatch (bool maxsum = true);

void init (int size)
{
	// 根據實際情況,添加代碼以初始化
	n = size;
	for (int i = 0; i < n; i ++)
		for (int j = 0; j < n; j ++)
			scanf ("%d", &weight [i] [j]);
}


bool path (int u)
{
	sx [u] = true;
	for (int v = 0; v < n; v ++)
		if (!sy [v] && lx[u] + ly [v] == weight [u] [v])
		{
			sy [v] = true;
			if (match [v] == -1 || path (match [v]))
			{
				match [v] = u;
				return true;
			}
		}
	return false;
}

int bestmatch (bool maxsum)
{
	int i, j;
	if (!maxsum)
	{
		for (i = 0; i < n; i ++)
			for (j = 0; j < n; j ++)
				weight [i] [j] = -weight [i] [j];
	}

	// 初始化標號
	for (i = 0; i < n; i ++)
	{
		lx [i] = -0x1FFFFFFF;
		ly [i] = 0;
		for (j = 0; j < n; j ++)
			if (lx [i] < weight [i] [j])
				lx [i] = weight [i] [j];
	}

	memset (match, -1, sizeof (match));
	for (int u = 0; u < n; u ++)	
		while (true)
		{
			memset (sx, 0, sizeof (sx));
			memset (sy, 0, sizeof (sy));
			if (path (u))
				break;

			// 修改標號
			int dx = 0x7FFFFFFF;
			for (i = 0; i < n; i ++)
				if (sx [i])
					for (j = 0; j < n; j ++)
						if(!sy [j])
							dx = min (lx[i] + ly [j] - weight [i] [j], dx);
			
			for (i = 0; i < n; i ++)
			{
				if (sx [i])
					lx [i] -= dx;
				if (sy [i])
					ly [i] += dx;
			}
		}

	int sum = 0;
	for (i = 0; i < n; i ++)
		sum += weight [match [i]] [i];

	if (!maxsum)
	{
		sum = -sum;
		for (i = 0; i < n; i ++)
			for (j = 0; j < n; j ++)
				weight [i] [j] = -weight [i] [j]; // 如果需要保持 weight [ ] [ ] 原來的值,這裏需要將其還原
	}
	return sum;
}


int main()
{
	int n;
	scanf ("%d", &n);
	init (n);
	int cost = bestmatch (true);

	printf ("%d \n", cost);
	for (int i = 0; i < n; i ++)	
	{
		printf ("Y %d -> X %d \n", i, match [i]);
	}
	system("pause");
	return 0;
}

/*
5
3 4 6 4 9
6 4 5 3 8
7 5 3 4 2
6 3 2 2 5
8 4 5 4 7
//執行bestmatch (true) ,結果爲 29
*/

/*
5
7 6 4 6 1
4 6 5 7 2
3 5 7 6 8
4 7 8 8 5
2 6 5 6 3
//執行 bestmatch (false) ,結果爲 21
*/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章