题目链接:http://poj.org/problem?id=3041
N*N的网格中,有K颗小行星,给出K棵小行星的位置,提供一个武器,一次可以消灭
一行星星或一列星星。求至少发多少枪可以将网格中的行星消灭殆尽。
光束作为图的顶点,小行星代表连接光束的边,横向是一个集合,纵向是一个集合,
一个行星可以从横向扫除去或纵向扫除去,就把它当作连接两个集合的边,则转化为
二分图匹配问题。
AC代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;
///行采取1~N编号,列采取N+1~2*N
const int maxn = 1005;
vector<int>node[maxn];
int N,K; ///N行N列的矩阵,K个行星
int vis[maxn];
int match[maxn];
bool hungry(int u)
{
for(int i = 0; i < (int)node[u].size(); i++)
{
int v = node[u][i];
if(vis[v] == 0)
{
vis[v] = 1;
if(match[v] == -1 || hungry(match[v]))
{
match[v] = u;
match[u] = v;
return true;
}
}
}
return false;
}
int solve()
{
memset(match,-1,sizeof(match));
int ans = 0;
for(int i = 1; i <= 2*N; i++)
{
if(match[i]==-1)
{
memset(vis,0,sizeof(vis));
if(hungry(i))
ans++;
}
}
return ans;
}
int main()
{
while(~scanf("%d%d",&N,&K))
{
int x,y;
for(int i = 1; i <= 2*N; i++)
node[i].clear();
for(int i = 1; i <= K; i++)
{
scanf("%d%d",&x,&y);
node[x].push_back(N+y);
node[N+y].push_back(x);
}
printf("%d\n",solve());
}
return 0;
}