Poj 3041 Asteroids

题目大意:给你一个N*N的矩阵,有一些格子里有小行星,现在Bessie有一些威力很大的炮弹,每一次射击都能够消灭掉矩阵中一行或一列的小行星,但是炮弹很贵,问你需要消灭掉所有小行星所需的最小炮弹数目。

思路:最小点覆盖的问题,将矩阵中每一个行看成集合A中的一个点,每一列看成集合B中的点如果第i行第j列有小行星则将Ai和Bj连一条边。题目要求的就是次二分图的最小点覆盖问题,在二分图中,最小点覆盖=最大匹配,可以使用匈牙利算法解决。

#include <iostream>
using namespace std;
const int SIZE = 520;
#include <stdio.h>
#include <memory.h>
int data[SIZE][SIZE];
int matched[SIZE];
int used[SIZE];
int n,k;
int dfs(int m) {
	int i;
	
	for ( i=1;i<=n;i++ ) {
		if ( used[i]==0&&data[m][i]==1 ) {
			used[i]=1;
			if ( matched[i]==-1||dfs(matched[i]) ) {
				matched[i]=m;
				return 1;
			}
		}
	}
	return 0;
}
/*求二分图的最小覆盖=最大二分匹配。最小覆盖:用最少的点(左右两边的点),让每条边都至少和其中一个点相关联。可以证明:最少的点(即覆盖数)=最大匹配数,最大匹配用匈牙利算法。matched数组记录right集中匹配的点的编号*/
int Hungary() {
	int i,ctr;
	ctr=0;
	for ( i=1;i<=n;i++ ) {
		memset(used,0,sizeof(used));
		if ( dfs(i) )
			ctr++;
	}
	return ctr;
}

int main()
{
	int i,result;
	int x,y;
	while ( scanf("%d%d",&n,&k)!=EOF ) {
		memset(data,0,sizeof(data));
		memset(matched,-1,sizeof(matched));
		for ( i=0;i<k;i++ ) {
			scanf("%d%d",&x,&y);
			data[x][y]=1;
		}
		result=Hungary();
		printf("%d\n",result);
	}
	return 0;
}


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