POJ-3041 二分图 最小覆盖点=最大匹配数 匈牙利算法

题意 :有一个N*N的网格,该网格有K个障碍物.你有一把武器,每次你使用武器可以清楚该网格特定行或列的所有障碍.问你最少需要使用多少次武器能清除网格的所有障碍物?

思路:

将每行、每列分别看作一个点,对于case的每一个行星坐标(x,y),将第x行和第y列连接起来,例如对于输入:

(1,1)、(1,3)、(2,2)、(3,2)4点构造图G:


这样,每个点就相当于图G的一条边,消灭所有点=消灭图G的所有边,又要求代价最少,即找到图G上的最少的点使得这些点覆盖了所有边。

根据定理吗, 最小点覆盖数=最大匹配数,所以本题转化为二分图的最大匹配问题——用匈牙利算法来解决。

#include<iostream>
#include<string>
using namespace std;
#define Max 505
int n, k;
int nx[Max], ny[Max];
int visit[Max];
int x, y, edgeM[Max][Max];
int M_F(int u)
{
	for (int i = 1; i <= n; i++)
	{
		if (edgeM[u][i] && !visit[i])
		{
			visit[i] = 1;
			if (ny[i] == -1 || M_F(ny[i]))
			{
				nx[u] = i;
				ny[i] = u;
				return 1;
			}
		}
	}
	return 0;
}
int M_make()
{
	int u;
	int res = 0;
	memset(nx, -1, sizeof(nx));
	memset(ny, -1, sizeof(ny));
	for (int i = 1; i <= n; i++)
	{
		memset(visit, 0, sizeof(visit));
		res += M_F(i);
	}
	return res;
}
int main()
{
	cin >> n >> k;
	for (int i = 0; i < k; i++)
	{
		cin >> x >> y;
		edgeM[x][y] = 1;
	}
	cout<<M_make()<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/usernamezzz/article/details/80642706