原题链接:点击打开链接
题意:从给出的位置中确定最多可以放置多少 “车” ,再确定若不在 哪些位置上放置 将会减少放置棋子的数量;
思路:
第一步:能放置棋子的位置 ,其横纵坐标都不能相同,横纵坐标看做两个集合(X集合,Y集合),给出的坐标点看做是X集合Y集合中两点的连线(二分图的边),所以现在 题意抽象成求二分图最大匹配数;
第二步:依次去掉给出能放置棋子的位置(即 去掉二分图的边),再次求最大匹配数,若与原图不同,则说明 现在去掉的是重要点;
code:
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
using namespace std;
int n,m;
const int MAX=550;
int map[MAX][MAX],vis[MAX],link[MAX];
struct Node{
int x,y;
}node[MAX];
int dfs(int s)
{
for(int i=1; i<=n; i++)
{
if(map[s][i] && !vis[i])
{
vis[i]=1;
if(link[i]==-1 || dfs(link[i]))
{
link[i]=s;
return true;
}
}
}
return false;
}
int hungary()
{
int i,ans=0;
memset(link,-1,sizeof(link));
for(i=1; i<=n; i++)
{
memset(vis,0,sizeof(vis));
if(dfs(i))
ans++;
}
return ans;
}
int main()
{
//freopen("i.txt","r",stdin);
int i,a,b,k;
int cot=0;
while(~scanf("%d%d%d",&n,&m,&k))
{
cot++;
memset(map,0,sizeof(map));
for(i=1;i<=k;i++)
{
scanf("%d%d",&a,&b);
map[a][b]=1;
node[i].x=a;node[i].y=b;
}
int ans1=hungary();
int ans2=0;
for(i=1;i<=k;i++)
{
map[node[i].x][node[i].y]=0;
int tem=hungary();
map[node[i].x][node[i].y]=1;
if(tem!=ans1)
ans2++;
}
// cout<<"*******\n"<<endl;
printf("Board %d have %d important blanks for %d chessmen.\n",cot,ans2,ans1);
}
return 0;
}