POJ 3041题
//题目类型:最小顶点覆盖问题
//题目大意:有一个N*N的格子,里面有-和*。一次命令可以消除某一行或某一列所有的*。请用最少的命令次数,消除所有的*。
//解题思路:最小点覆盖:在二分图中,选择最少的点,使得每一边都至少有端点被覆盖。
//Konig定理:最小点覆盖数=最大匹配数
//于是,将格子转化成左边N个点,右边N个点的二分图。边XiYj表示i,j有*。这样,只要这条边被选择,所有这一行的*都被消除,因为他们的边都一定有端点Xi.
//匈牙利算法就可以了
#include <iostream>
//#include <conio.h>
using namespace std;
#define arraysize 501
int n,k;
bool map[arraysize][arraysize];
int match[arraysize];
bool final[arraysize];
bool DFS(int p)
{
int i;
int temp;
for(i=1;i<n+1;++i)
{
if(map[p][i] && !final[i])
{
final[i] = true;
temp = match[i];
match[i] = p;
if(temp == 0 || DFS(temp)) return true;
match[i] = temp;
}
}
return false;
}
int mat()
{
int i,j;
int maxmatch = 0;
for(i=1;i<n+1;++i)
{
memset(final,0,sizeof(final));
if(DFS(i)) maxmatch++;
}
return maxmatch;
}
int main()
{
//freopen("1.txt","r",stdin);
int i,j;
while(cin>>n>>k)
{
int r,c;
memset(map,0,sizeof(map));
memset(match,0,sizeof(match));
for(i=0;i<k;++i)
{
cin>>r>>c;
map[r][c] = 1;
}
cout<<mat()<<endl;
}
//getch();
return 0;
}