把每行看作一点,每列看作一点,可以放置的格子就是边,连接其所在行和列两点
那么用二分图最大匹配很容易就求出来,最多可以放置多少车
然后对于每个给出的格子,在求一次没有这个格子的最大匹配,如果小于原来的匹配,说明这是重要的格子
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
const int N=100+10;
const int M=1e4+10;
bool g[N][N];
int linker[N];
bool used[N];
int n,m,k;
bool dfs(int u)
{
for(int i=1;i<=m;i++)
{
if(used[i]||!g[u][i]) continue;
used[i]=true;
if(linker[i]==-1||dfs(linker[i]))
{
linker[i]=u;
return true;
}
}
return false;
}
int hungary()
{
int res=0;
memset(linker,-1,sizeof(linker));
for(int i=1;i<=n;i++)
{
memset(used,false,sizeof(used));
if(dfs(i)) res++;
}
return res;
}
int a[M],b[M];
int main()
{
int kase=0;
while(~scanf("%d%d%d",&n,&m,&k))
{
memset(g,false,sizeof(g));
for(int i=0;i<k;i++)
{
scanf("%d%d",&a[i],&b[i]);
g[a[i]][b[i]]=true;
}
int num=hungary();
int ans=0;
for(int i=0;i<k;i++)
{
g[a[i]][b[i]]=false;
if(hungary()<num) ans++;
g[a[i]][b[i]]=true;
}
printf("Board %d have %d important blanks for %d chessmen.\n",++kase,ans,num);
}
return 0;
}