这这这。。。 稍微感受一下建图的不一样吧吧吧。。。
原先说二分图匹配可以解决n皇后问题,原来是这样用的。。。把行列对应起来,由于是匹配,所以不会出现每行或者每列出现重复的情况。
这道题也是,先用匈牙利算出最大匹配,然后挨个删边,看哪个删完之后边数变少了,那就是他啦!!
嗯,注意初始化。
#include <stdio.h>
#include <string.h>
#define maxn 110
int girl[maxn],map[maxn][maxn],vis[maxn];
int n,m,p;
int find(int x)
{
int i,j,k;
for(i=1;i<=m;i++)
{
if(map[x][i]&&!vis[i])
{
vis[i]=1;
if(!girl[i]||find(girl[i]))
{
girl[i]=x;//printf("girl[%d]=%d\n",i,x);
return 1;
}
}
}
return 0;
}
int work()
{
int i,j,k;
int ret=0;
memset(girl,0,sizeof(girl)); //刚开始的时候把这个初始化放在了init()里,导致后面删边的时候出错了。。。
for(i=1;i<=n;i++)
{
memset(vis,0,sizeof(vis));
if(find(i)) ret++;
}
return ret;
}
void init()
{
memset(map,0,sizeof(map));
}
int main()
{
int cas=0;
while(scanf("%d%d%d",&n,&m,&p)!=EOF)
{
cas++;
init();
int i,j,k;
for(i=0;i<p;i++)
{
scanf("%d%d",&j,&k);
map[j][k]=1;
}
int ans=work();
int ret=0;
//printf("**********\n");
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
if(map[i][j])
{
map[i][j]=0;
if(work()<ans) ret++;
// printf("tmp=%d x=%d y=%d\n",work(),i,j);
map[i][j]=1;
}
}
}
printf("Board %d have %d important blanks for %d chessmen.\n",cas,ret,ans);
}
return 0;
}