传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1281
输入:先输入棋盘大小,然后输入K个可以放“車”的点(可容点)。
输出:第cnt个数据,“重要点”个数,可以放几个“車”。
“重要点”:去掉Map[i][j]点后放置“車”的数量会减少,那么这个点为重要点,否则不是重要点。
思路:先算出能放置的最大“車”数ans;
对每个可容点遍历,将可容点变成不可容点,再计算可放置“車”数answer(),如果可放置“車”数少了,即(answer()<ans),那么这点自然就是重要点了(num++)。
AC代码:
#include<iostream>
#include<cstring>
using namespace std;
bool Map[123][123],vis[123];
int Link[123],M,N;
bool Find(int x)
{
for(int i=1;i<=N;i++)
{
if(!vis[i]&&Map[x][i])
{
vis[i]=1;
if(!Link[i]||Find(Link[i]))
{
Link[i]=x;
return 1;
}
}
}
return 0;
}
int answer()
{
int ans=0;
for(int i=0;i<=M;i++)
{
memset(vis,0,sizeof(vis));
if(Find(i)) ans++;
}
return ans;
}
int main()
{
int cnt=0;
int K;
while(cin>>M>>N>>K)
{
memset(Map,0,sizeof(Map));
memset(Link,0,sizeof(Link));
while(K--)
{
int a,b;
cin>>a>>b;
Map[a][b]=1;
}
int ans=answer();
int num=0;
for(int i=1;i<=M;i++)
{
for(int j=1;j<=N;j++)
{
if(Map[i][j])
{
memset(Link,0,sizeof(Link)); //每次都要重新定义链接线
Map[i][j]=0;
if(answer()<ans) num++;
Map[i][j]=1;
}
}
}
printf("Board %d have %d important blanks for %d chessmen.\n",++cnt,num,ans);
}
return 0;
}