bzoj2437 [Noi2011]兔兔与蛋蛋

二分图博弈果然都是一个套路,必经点必胜,非必经点必败,

但是肯定不能每走一步就重新建图判断必胜还是必败,那么我们可以这样:每走一步就把这个点删掉,然后find他原来的匹配,如果找不到,就说明他是必经点,否则就是非必经点。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cmath>
 6 #define N 1601
 7 using namespace std;
 8 int e=1,head[N];
 9 struct edge{int v,next;}ed[N*4];
10 void add(int u,int v){ed[e].v=v;ed[e].next=head[u];head[u]=e++;}
11 int pp[N],del[N],id[41][41];
12 bool vis[N],ans[N];
13 bool find(int x){
14     for(int i=head[x];i;i=ed[i].next){
15         int v=ed[i].v;
16         if(del[v]||vis[v])continue;vis[v]=1;
17         if(!pp[v]||find(pp[v])){
18             pp[v]=x;pp[x]=v;
19             return 1;
20         }
21     }return 0;
22 }
23 int a[41][41],be,n,m,T,sx,sy,tot1,tot2,tot;
24 char ch[41];
25 bool check(int i,int j){return ((i+j)&1)^a[i][j]==be;}
26 int f[N],f_cnt;
27 int main(){
28     scanf("%d%d",&n,&m);
29     for(int i=1;i<=n;i++){
30         scanf("%s",ch+1);
31         for(int j=1;j<=m;j++)
32             if(ch[j]=='O')a[i][j]=1;
33             else if(ch[j]=='X')a[i][j]=0;
34             else sx=i,sy=j;
35     }
36     be=(sx+sy)&1;
37     for(int i=1;i<=n;i++)
38         for(int j=1;j<=m;j++)if(check(i,j))
39             if(a[i][j])id[i][j]=++tot1;
40             else id[i][j]=++tot2;
41     for(int i=1;i<=n;i++)
42         for(int j=1;j<=m;j++)if(check(i,j)&&(!a[i][j]))
43             id[i][j]+=tot1;
44     tot=tot1+tot2;
45     for(int i=1;i<=n;i++)
46         for(int j=1;j<=m;j++)if(id[i][j]){
47             if(id[i+1][j])add(id[i][j],id[i+1][j]);
48             if(id[i][j+1])add(id[i][j],id[i][j+1]);
49             if(id[i-1][j])add(id[i][j],id[i-1][j]);
50             if(id[i][j-1])add(id[i][j],id[i][j-1]);
51         }
52     for(int i=1;i<=tot1;i++){
53         memset(vis,0,sizeof vis);
54         find(i);
55     }
56     scanf("%d",&T);T<<=1;
57     for(int i=1,x,y;i<=T;i++){
58         int now=id[sx][sy],p=pp[now];
59         del[now]=1;pp[now]=pp[p]=0;
60         if(!p)ans[i]=0;
61         else{
62             memset(vis,0,sizeof vis);
63             ans[i]=find(p)^1;
64         }
65         scanf("%d%d",&sx,&sy);
66     }
67     for(int i=1;i<=T;i+=2)
68         if(ans[i]&&ans[i+1])f[++f_cnt]=(i+1)>>1;
69     printf("%d
",f_cnt);
70     for(int i=1;i<=f_cnt;i++)
71         printf("%d
",f[i]);
72     return 0;
73 }
View Code
原文地址:https://www.cnblogs.com/Ren-Ivan/p/8352969.html