http://acm.hust.edu.cn/vjudge/contest/view.action?cid=69427#problem/E
Description
小希和Gardon在玩一個遊戲:對一個N*M的棋盤,在格子裏放盡量多的一些國際象棋裏面的“車”,並且使得他們不能互相攻擊,這當然很簡單,但是Gardon限制了只有某些格子纔可以放,小希還是很輕鬆的解決了這個問題(見下圖)注意不能放車的地方不影響車的互相攻擊。所以現在Gardon想讓小希來解決一個更難的問題,在保證儘量多的“車”的前提下,棋盤裏有些格子是可以避開的,也就是說,不在這些格子上放車,也可以保證儘量多的“車”被放下。但是某些格子若不放子,就無法保證放盡量多的“車”,這樣的格子被稱做重要點。Gardon想讓小希算出有多少個這樣的重要點,你能解決這個問題麼?
Input
輸入包含多組數據,
第一行有三個數N、M、K(1<N,M<=100 1<K<=N*M),表示了棋盤的高、寬,以及可以放“車”的格子數目。接下來的K行描述了所有格子的信息:每行兩個數X和Y,表示了這個格子在棋盤中的位置。
Output
對輸入的每組數據,按照如下格式輸出:
Board T have C important blanks for L chessmen.
Sample Input
3 3 4
1 2
1 3
2 1
2 2
3 3 4
1 2
1 3
2 1
3 2
Sample Output
Board 1 have 0 important blanks for 2 chessmen.
Board 2 have 3 important blanks for 3 chessmen.
分析:建邊是根據行和列建的,要找哪些是關鍵點,先求一次最大匹配ans1,然後枚舉哪些條邊刪除,如果刪除了這邊,再求最大匹配ans2,
if(ans2!=ans1)則說明這條邊不能刪,這個點是關鍵點
#include <iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int map[105][105],mat[105][105];
int v[105],p[105];
int n,m;
int match(int i)
{
int j;
for(j=1;j<=m;j++)
{
if(map[i][j]==1&&v[j]==0)
{
v[j]=1;
if(p[j]==-1||match(p[j]))
{
p[j]=i;
return 1;
}
}
}
return 0;
}
int hungary()
{
int i,re=0;
memset(p,-1,sizeof(p));
for(i=1;i<=n;i++)
{
memset(v,0,sizeof(v));
if(match(i))
{
re++;
}
}
return re;
}
int main()
{
int k,i,a,b,ans,sum,ans1,ji1,t=1,j;
int pp[105];
while(scanf("%d%d%d",&n,&m,&k)!=EOF)
{
memset(map,0,sizeof(map));
for(i=1;i<=k;i++)
{
scanf("%d%d",&a,&b);
map[a][b]=1;
mat[a][b]=1;
}
ans=hungary();
sum=0;
for(i=1;i<=104;i++)
{
pp[i]=p[i];
}
for(j=1;j<=m;j++)
{
if(pp[j]!=-1)
{
map[pp[j]][j]=0;
ans1=hungary();
if(ans1<ans)
sum++;
map[pp[j]][j]=1;
}
}
printf("Board %d have %d important blanks for %d chessmen.\n",t++,sum,ans);
}
return 0;
}