poj3020 匈牙利算法+公式:二分无向图的最小路径覆盖 = 顶点数 - 最大二分匹配数 / 2

这道题想了很久,预先知道是匈牙利算法,但是呢,实在没法和二分图联系起来,尤其是怎么想最大点集覆盖和最大匹配都不行。

磨蹭两个小时,跑去看答案,小优的答案很详细,大家自己看吧:

http://blog.csdn.net/lyy289065406/article/details/6647040

基本的思想是:

无向二分图的最小路径覆盖 = 顶点数 – 最大二分匹配数/2

构造一个无向二分图,然后利用匈牙利算法,公式,主要在于二分图的构造上,小优说得很详细,但是我不是很懂其实。一次AC。

//poj3020
#include <iostream>
using namespace std;
int grid[50][20];
int map[1000][1000];
int visit[10000];
int link[1000];
int m;
bool dfs(int x, int n)
{
	for (int i = 1; i <= n; i++)
	{
		if (map[x][i] == 1 && !visit[i])
		{
			visit[i] = true;
			if(link[i] == 0 || dfs(link[i], n))
			{
				link[i] = x;
				return true;
			}
		}
	}
	return false;
}
int search(int n)
{
	for (int i = 1; i <= n; i++)
	{
		memset(visit, 0, sizeof(visit));
		if (dfs(i, n))
			m++;
	}
	return m;
}
int main()
{
	int n;
	cin >> n;
	while (n--)
	{
		memset(grid, 0, sizeof(grid));
		memset(map, 0, sizeof(map));
		memset(link, 0, sizeof(link));
		int a, b;
		cin >> a >> b;
		int num = 0;
		char c;
		m = 0;
		for (int i = 0; i < a; i++)
		{
			for (int j = 0; j < b; j++)
			{
				cin >> c;
				if (c == '*')
				{
					num++;
					grid[i][j] = num;
				}
				else
					grid[i][j] = 0;
			}
		}
		for (int i = 0; i < a; i++)
		{
			for (int j = 0; j < b; j++)
			{
				if (grid[i][j])
				{
					if (i - 1 >= 0 && grid[i - 1][j])
					{
						map[grid[i][j]][grid[i - 1][j]] = 1;
						map[grid[i - 1][j]][grid[i][j]] = 1;
					}
					if (i + 1 < a && grid[i + 1][j])
					{
						map[grid[i][j]][grid[i + 1][j]] = 1;
						map[grid[i + 1][j]][grid[i][j]] = 1;
					}
					if (j - 1 >= 0 && grid[i][j - 1])
					{
						map[grid[i][j]][grid[i][j - 1]] = 1;
						map[grid[i][j - 1]][grid[i][j]] = 1;
					}
					if (j + 1 < b && grid[i][j + 1])
					{
						map[grid[i][j]][grid[i][j + 1]] = 1;
						map[grid[i][j + 1]][grid[i][j]] = 1;
					}
				}
			}
		}
		int mapnum = search(num);
		cout << num - mapnum / 2<< endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/chchlh/article/details/42194733