题目链接:棋盘游戏
题目大意:给定一个n*m的棋盘,其中k个格子可以放车(车可以横着走和竖着走即攻击,不限步数),要求同一行或者同一列不能放多余一辆车。如果去掉一个位置的车,所能放的最多车的数目减少,就称为重要点,求重要点的个数。
题目分析:典型的行列匹配题,由于某行或某列最多放一个车,当某点放车时,该点的行和列之间就连一条边,边数就是能放的最多的车数。
暴力解法:每次去掉一个点,即去掉一条边,重新计算匹配数(最多的车数),如变少,则该点就是重要点。
复杂度:O(E*V^2)
#include <stdio.h>
#include <memory.h>
const int maxn=105;
bool vis[maxn];
int g[maxn][maxn],link[maxn];
int n,m,k;
int dfs(int u)
{
for(int v=1;v<=m;v++){
if(g[u][v]&&!vis[v]){
vis[v]=true;
if(link[v]==-1||dfs(link[v])){
link[v]=u;
return 1;
}
}
}
return 0;
}
int hungry()
{
int cnt=0;
memset(link,-1,sizeof(link));
for(int u=1;u<=n;u++){
memset(vis,0,sizeof(vis));
cnt+=dfs(u);
}
return cnt;
}
int main()
{
//freopen("in.txt","r",stdin);
int x[maxn*maxn],y[maxn*maxn];
int T=1;
while(scanf("%d %d %d",&n,&m,&k)!=EOF){
memset(g,0,sizeof(g));
int import=0;
for(int i=0;i<k;i++){
scanf("%d %d",&x[i],&y[i]);
g[x[i]][y[i]]=1;
}
int ans=hungry();
for(int i=0;i<k;i++){
g[x[i]][y[i]]=0;
int tmp=hungry();
if(tmp<ans)import++;1;
g[x[i]][y[i]]=1;
}
printf("Board %d have %d important blanks for %d chessmen.\n",T++,import,ans);
}
return 0;
}