题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1281
题目大意:
每个车不能碰面,灰色不能放车,问最多可以放多少个车。关键的空位:如果这个位置不能放车的话。那么现在可以放的车的数量比之前少。
思路:最开始求最大匹配,然后枚举每一条边,拆了,最大匹配是否会减少?是,这就是关键边。
#include <bits/stdc++.h>
using namespace std;
int n,m, k, T=0;//顶点数n和边的数目m
int e[151][151];//保存一个无向图
int book[151];//每次都标记那个去了和那个没去
int match[151];//标记那个是匹配那个的
#define inf 9999//假设的无穷大
int dfs (int u)
{
int i;
for (i=1;i<=n;i++)
{
if (book[i]==0&&e[u][i]==1)//这个点在同一次上没去过,而且他们能联通
{
book[i]=1;//这个点已经尝试过了
if (match[i]==0||dfs(match[i]))//这个点还没有被匹配,
//或者,他可以匹配其他的人
{
//他们就能够匹配
match[i]=u;//判断哪个,就是修改那个
//match[u]=i;不用的,错误的
return 1;
}
}
}
return 0;
}
int work ()
{
memset(match, 0, sizeof(match));
int i_count=0;
for (int i=1;i<=n;i++)//尝试遍历每一个顶点
{
memset (book,0,sizeof(book));
if (dfs(i))
{
i_count++;//若能找到新的匹配,就++
}
}
return i_count;
}
int x[10100], y[10100];
int main ()
{
while(~scanf("%d%d%d",&n,&m,&k))
{
T++;
memset(e, 0, sizeof(e));
for (int i=1;i<=k;i++)
{
int u,v;
scanf ("%d%d",&x[i],&y[i]);
e[x[i]][y[i]]=1;
}
int ans=work ();
int cut=0;
for(int i=1;i<=k;i++)
{
e[x[i]][y[i]]=0;
if(ans!=work ())
{
cut++;
}
e[x[i]][y[i]]=1;
}
printf("Board %d have %d important blanks for %d chessmen.\n",T, cut, ans);
}
return 0;
}