原题:http://acm.hdu.edu.cn/showproblem.php?pid=1281
/*
思路:二分图的最大匹配
要明白,同一行或同一列不能同时有两个 车,就是两个车的坐标x或y不能相同。
其实整个棋盘可以 看成一个矩阵,可以将其画成二分图------左边是x坐标,右边是y坐标
模拟这个过程:我们想尽全力在每一行都放一个车,即先从不同的x出发(这样就保证了行不一样),
接着尽量让每一个x都找到未被使用的y(这样保证了列与其他的不一样),画成图就是让一个x连线到一个y,最多车能放的数目即为这个二分图的最大匹配ans
求出能放车的最大数目后,再依次去掉各个点,看是否会减少 ans,如果会,该店点就是重要点。
*/
#include<stdio.h>
#include<memory.h>
int a[101][101];
int used[101];
int pair[101];
int left[101*101];
int right[101*101];
int n,m,k;
bool find(int x)
{
for(int i=1;i<=m;i++)
{
if(a[x][i]==1 && used[i]==0)
{
used[i]=1;
if(pair[i]==0 || find(pair[i])==true)
{
pair[i]=x;
return true;
}
}
}
return false;
}
int main()
{
int t=0;
while(~scanf("%d %d %d",&n,&m,&k))
{
t++;
memset(a,0,sizeof(a));
memset(pair,0,sizeof(pair));
for(int i=1;i<=k;i++)
{
scanf("%d %d",&left[i],&right[i]);
a[left[i]][right[i]]=1;
}
int ans=0;//最大匹配
int rs=0;//重要点
for(int i=1;i<=n;i++)
{
memset(used,0,sizeof(used));
if(find(i)){
ans++;
}
}
for(int i=1;i<=k;i++)
{
memset(pair,0,sizeof(pair));//初始化,所有还没有配对
a[left[i]][right[i]]=0;
int tmp=0;
int j;
for(j=1;j<=n;j++)
{
memset(used,0,sizeof(used));
if(find(j)){
tmp++;
}
}
a[left[i]][right[i]]=1;
if(tmp<ans)
{
rs++;
}
}
printf("Board %d have %d important blanks for %d chessmen.\n",t,rs,ans);
}
return 0;
}