小希和Gardon在玩一个游戏:对一个N*M的棋盘,在格子里放尽量多的一些国际象棋里面的“车”,并且使得他们不能互相攻击,这当然很简单,但是Gardon限制了只有某些格子才可以放,小希还是很轻松的解决了这个问题(见下图)注意不能放车的地方不影响车的互相攻击。
所以现在Gardon想让小希来解决一个更难的问题,在保证尽量多的“车”的前提下,棋盘里有些格子是可以避开的,也就是说,不在这些格子上放车,也可以保证尽量多的“车”被放下。但是某些格子若不放子,就无法保证放尽量多的“车”,这样的格子被称做重要点。Gardon想让小希算出有多少个这样的重要点,你能解决这个问题么?
先DFS求出点数,再用二分匹配求解
1 #include<stdio.h>
2 #include<string.h>
3
4 const int maxn=1e5+5;
5 const int maxm=1e5+5;
6
7 int head[maxn],point[maxm],nxt[maxm],size;
8 int match[maxn],vis[maxn];
9 int get[maxn];
10
11 void init(){
12 memset(head,-1,sizeof(head));
13 size=0;
14 memset(match,-1,sizeof(match));
15 memset(get,-1,sizeof(get));
16 }
17
18 void add(int a,int b){
19 point[size]=b;
20 nxt[size]=head[a];
21 head[a]=size++;
22 }
23
24 int del;
25
26 int dfs(int s,bool F){
27 for(int i=head[s];~i;i=nxt[i]){
28 if(!F&&i==del)continue;
29 int j=point[i];
30 if(!vis[j]){
31 vis[j]=1;
32 if(match[j]==-1||dfs(match[j],F)){
33 if(F){
34 match[j]=s;
35 get[s]=i;
36 }
37 return 1;
38 }
39 }
40 }
41 return 0;
42 }
43
44
45 int main(){
46 int T=0;
47 int n,m,k;
48 while(scanf("%d%d%d",&n,&m,&k)!=EOF){
49 ++T;
50 init();
51 while(k--){
52 int a,b;
53 scanf("%d%d",&a,&b);
54 add(a,n+b);
55 }
56 int ans1=0;
57 for(int i=1;i<=n;++i){
58 memset(vis,0,sizeof(vis));
59 if(dfs(i,1))ans1++;
60 }
61 int ans=0;
62 for(int i=1;i<=n;++i){
63 if(get[i]!=-1){
64 del=get[i];
65 match[point[del]]=-1;
66 get[i]=-1;
67 memset(vis,0,sizeof(vis));
68 if(!dfs(i,0))ans++;
69 get[i]=del;
70 match[point[del]]=i;
71 }
72 }
73 printf("Board %d have %d important blanks for %d chessmen.
",T,ans,ans1);
74 }
75 return 0;
76 }