Poj 3041 Asteroids

来源:互联网 发布:php专业培训 编辑:程序博客网 时间:2024/05/17 22:34
题目大意:给你一个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;}


原创粉丝点击