这道题如果读懂了,就很简单。
大致题意:
一个n*m的棋盘,有k个可以放‘車’的格子,放完‘車’之后,要保证不能互相攻击。
假设最多能放t个‘車’。
如果某个能放‘車’的格子现在不可以放了,且结果最多能放的‘車’数目不是t了,就称这个格子为重要点。
最后输出重要点的数目和t。
大致思路:
先将最大数目求出来,也就是利用行和列(将可放的格子的行和列进行连边)两个集合求出最大匹配ans。
然后在一一枚举每个格子不可以放的时候,再求出最大匹配数,看看是否为ans,不是的话,则为重要点。
代码:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
int ma[200][200];
int x[200];
int y[200];
int lx[200];
int rx[200];
int vis[200];
int n,m,k;
int dfs(int k)
{
for(int i=1; i<=m; i++)
{
if(ma[k][i]&&!vis[i])
{
vis[i]=1;
if(rx[i]==-1||dfs(rx[i]))
{
lx[k]=i;
rx[i]=k;
return true;
}
}
}
return false;
}
int main()
{
int fas=0;
while(~scanf("%d%d%d",&n,&m,&k))
{
memset(ma,0,sizeof(ma));
memset(lx,-1,sizeof(lx));
memset(rx,-1,sizeof(rx));
int ans=0;
int r,c;
for(int i=1; i<=k; i++)
{
scanf("%d%d",&r,&c);
x[i]=r;
y[i]=c;
ma[r][c]=1;
}
for(int i=1; i<=n; i++)
{
memset(vis,0,sizeof(vis));
if(lx[i]==-1&&dfs(i))
{
ans++;
}
}
int kas;
int cas=0;
for(int i=1; i<=k; i++)
{
ma[x[i]][y[i]]=0;//这个格子不可以放了
memset(lx,-1,sizeof(lx));
memset(rx,-1,sizeof(rx));
kas=0;
for(int i=1; i<=n; i++)
{
memset(vis,0,sizeof(vis));
if(lx[i]==-1&&dfs(i))
{
kas++;
}
}
//cout<<"++"<<x[i]<<" "<<y[i]<<" "<<kas<<endl;
if(kas!=ans)
{
cas++;
}
ma[x[i]][y[i]]=1;//回溯
}
printf("Board %d have %d important blanks for %d chessmen.\n",++fas,cas,ans);
}
}