题意:一张图上有许多障碍物,一发炮弹能摧毁一行或一列的障碍物,问最少需要几发
思路:把每行看成匹配的左列,把列看成匹配的右列,(i,j)这个点表示需要第i行或第j列的一发炮弹即可,认为它们有一条边。那么现在问题就变为最少需要几个点,这些点延伸出的边能覆盖所有点。最小点覆盖 = 最大匹配数
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<stdlib.h>
#include<math.h>
#include<vector>
#include<list>
#include<map>
#include<stack>
#include<queue>
#include<algorithm>
#include<numeric>
#include<functional>
using namespace std;
typedef long long ll;
const int maxn = 505;
int girl[maxn],vis[maxn],num[maxn][maxn],n,m;
void init(int x)
{
memset(girl,-1,sizeof girl);
memset(num,0,sizeof num);
}
int fid(int x) // 为匹配x
{
for(int j = 1; j <= n; j++)
{
if(!vis[j] && num[x][j])
{
vis[j] = 1;
if(girl[j] == -1 || fid(girl[j]) )
{
girl[j] = x;
return 1;
}
}
}
return 0;
}
int main(void)
{
while(scanf("%d%d",&n,&m)!=EOF)
{
init(n);
for(int i = 1; i <= m; i++)
{
int a,b;
scanf("%d%d",&a,&b);
num[a][b] = i;
}
int ans = 0;
for(int i = 1; i <= n; i++)
{
memset(vis,0,sizeof vis);
if(fid(i))
ans++;
}
printf("%d\n",ans);
}
return 0;
}