小行星
题目
贝西想以N x N网格(1 <= N <= 500)的形状在危险的小行星场中导航她的飞船。网格包含K个小行星(1 <= K <= 10,000),它们方便地位于网格的晶格点处。
幸运的是,贝茜拥有强大的武器,可以一击就蒸发掉网格中任何给定行或列中的所有小行星,这种武器非常昂贵,因此她希望谨慎使用。字段中,找到贝西需要射击以消除所有小行星的最小射击次数。
输入
第1行:两个整数N和K,以单个空格分隔。
第2…K + 1行:每行包含两个空格分隔的整数R和C(1 <= R,C <= N),分别表示小行星的行和列座标。
输出
第1行:整数,表示Bessie必须拍摄的最小次数。
输入样例
3 4
1 1
1 3
2 2
3 2
输出样例
2
输入详细信息
下图表示数据,其中“ X”是小行星,“。”。是空白空间:
X 。 X
。 X 。
。 X 。
输出详细信息
Bessie可以越过第1行射击以摧毁和处的小行星,然后她可以击落第2列以摧毁和处的小行星。
解题思路
其实这道题就是最大匹配的模板,把每个行星的的和分别列成一行,建二分图,然后把行星的和的座标连起来,在查找最大匹配即可.
程序如下
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int n,k,kk,x,y,head[100001],s[100001],l[100001],ans;
struct node
{
int to,next;
}f[1000001];
int find(int t)
{
for (int i = head[t]; i; i = f[i].next)
{
int j = f[i].to;
if (!s[j])
{
int q = l[j];
l[j] = t;
s[j] = 1;
if (!q || find(q)) return 1;
l[j] = q;
}
}
return 0;
}
int main()
{
scanf("%d%d",&n,&k);
for(int i = 1;i <= k; ++i)
{
scanf("%d%d",&x,&y);
f[++kk].next = head[x];
f[kk].to = y;
head[x] = kk;
}
for(int i = 1;i <= n; ++i)
{
memset(s,0,sizeof(s));
ans += find(i);
}
printf("%d",ans);
return 0;
}