POJ-3041 Asteroids

题目链接:http://poj.org/problem?id=3041

题目大意:

给你一个nxn的方阵,X代表一个敌人,可以在方阵内放置炸弹,炸弹可以炸掉所在在一行或者所在的一列,求最少需要多少个炸弹才能炸掉所有的敌人。


解题思路:

我们可以把行的坐标当成X集合,列坐标当成Y集合,那么每个敌人就是一条边。这样就构成了一个二分图。要求的是二分图最小点集覆盖。由定理可知,二分图最小点集覆盖等于最大匹配。所以,用匈牙利算法求出最大匹配即可。


代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define M 510 
#define N 10010
int Head[M], Next[N], Key[N];
int match[M];
bool use[M];
int num;


void add(int u, int v)
{
	Key[num] = v;
	Next[num] = Head[u];
	Head[u] = num++;
}


bool find(int u)
{
	int temp;
	for(int i = Head[u]; i != -1; i = Next[i])
	{
		temp = Key[i];
		if(!use[temp])
		{
			use[temp] = true;
			if(match[temp] == -1 || find(match[temp]))
			{
				match[temp] = u;
				return true;
			}
		}
	}
	return false;
}


int hungary(int n)
{
	int sum = 0;
	for(int i = 1; i <= n; ++i)
	{
		memset(use, false, sizeof(use));
		if(find(i))
			sum++;
	}
	return sum;
}


int main()
{
	int size, des;
	int x, y;
	while(scanf("%d%d", &size, &des)  != EOF)
	{
		num = 0;
		memset(Head, -1, sizeof(Head));
		memset(match, -1, sizeof(match));
		for(int i = 1; i <= des; ++i)
		{
			scanf("%d%d", &x, &y);
			add(x, y);
		}
		printf("%d\n", hungary(size));
	}
	return 0;
}  

      

你可能感兴趣的:(POJ-3041 Asteroids)