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\n",f_cnt); 70 for(int i=1;i<=f_cnt;i++) 71 printf("%d\n",f[i]); 72 return 0; 73 }
人生如梦亦如幻 朝如晨露暮如霞。