[BZOJ]2437: [Noi2011]兔兔与蛋蛋 二分图匹配+博弈
2017-09-14 12:52
369 查看
题解:
神题……%%%FYC。首先我们将问题转化为:空格先走一个白点再走一个黑点……谁不能走谁输。由于先走白点,所以可以将起点的空格看做一个黑点。我们又可以将这个图看做二分图,一黑一白这样走可以看做是二分图匹配里面找增广路的过程,因为增广路最后的终点在白点,所以对于任意一种情况,只需要找到一条从起点出发的增广路,就是必胜。对于任意情况都能找到,当且仅当起点一定在二分图的最大匹配中。那么怎么找呢?只需要把它的原匹配切掉,再跑一次二分图匹配就好了。注意每次要把空格位置这个点标记删掉,因为原来的边已经不能到达它了。
代码:
神题……%%%FYC。首先我们将问题转化为:空格先走一个白点再走一个黑点……谁不能走谁输。由于先走白点,所以可以将起点的空格看做一个黑点。我们又可以将这个图看做二分图,一黑一白这样走可以看做是二分图匹配里面找增广路的过程,因为增广路最后的终点在白点,所以对于任意一种情况,只需要找到一条从起点出发的增广路,就是必胜。对于任意情况都能找到,当且仅当起点一定在二分图的最大匹配中。那么怎么找呢?只需要把它的原匹配切掉,再跑一次二分图匹配就好了。注意每次要把空格位置这个点标记删掉,因为原来的边已经不能到达它了。
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn=2010; int n,m,k,a[maxn],b[maxn],map[50][50],num[50][50]; struct Edge{int y,next;}e[maxn*4]; int last[maxn],len=0; void ins(int x,int y) { int t=++len; e[t].y=y;e[t].next=last[x];last[x]=t; } int chw[maxn],match[maxn],T=0; bool win[maxn],del[maxn]; bool findmatch(int x) { if(del[x])return false; for(int i=last[x];i;i=e[i].next) { int y=e[i].y; if(chw[y]!=T&&!del[y]) { chw[y]=T; if(!match[y]||findmatch(match[y])) { match[y]=x;match[x]=y; return true; } } } return false; } int Ans[maxn],la=0; int main() { int xx,yy,z=0; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { char str[45]; scanf("%s",str+1); for(int j=1;j<=m;j++) { if(str[j]=='X')map[i][j]=1; else if(str[j]=='O')map[i][j]=0; else map[i][j]=1,xx=i,yy=j; } }//1黑0白 for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if((map[i][j]&&((abs(xx-i)+abs(yy-j))&1)==0)||(!map[i][j]&&(abs(xx-i)+abs(yy-j))&1))num[i][j]=++z; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(num[i][j]) { if(i<n&&num[i+1][j])ins(num[i][j],num[i+1][j]); if(i>1&&num[i-1][j])ins(num[i][j],num[i-1][j]); if(j<m&&num[i][j+1])ins(num[i][j],num[i][j+1]); if(j>1&&num[i][j-1])ins(num[i][j],num[i][j-1]); } for(int i=1;i<=z;i++) if(!match[i]) { T++; findmatch(i); } scanf("%d",&k); for(int i=1;i<=k*2;i++) { int tt=num[xx][yy]; del[tt]=true; if(match[tt]) { int M=match[tt]; match[tt]=match[M]=0; T++; win[i]=(!findmatch(M)); } else win[i]=false; scanf("%d%d",&xx,&yy); } for(int i=1;i<=k*2;i+=2) if(win[i]&&win[i+1])Ans[++la]=(i+1)/2; fe40 printf("%d\n",la); for(int i=1;i<=la;i++) printf("%d\n",Ans[i]); }
相关文章推荐
- bzoj 2437: [Noi2011]兔兔与蛋蛋 博弈论+二分图匹配
- [BZOJ 2437][NOI 2011]兔兔与蛋蛋(二分图匹配)
- bzoj 2437 [Noi2011]兔兔与蛋蛋 [二分图匹配]
- [BZOJ]2437 [NOI2011] 兔兔与蛋蛋 二分图博弈
- 【bzoj2437】【NOI2011】【兔兔与蛋蛋】【二分图博弈】
- [二分图博弈] BZOJ 1443 [JSOI2009]游戏Game & BZOJ 2437 [Noi2011]兔兔与蛋蛋
- bzoj 2437: [Noi2011]兔兔与蛋蛋
- bzoj 2437: [Noi2011]兔兔与蛋蛋 (二分图博弈+dinic)
- 2437: [Noi2011]兔兔与蛋蛋 - BZOJ
- BZOJ 2437: [Noi2011]兔兔与蛋蛋
- bzoj2437 [Noi2011]兔兔与蛋蛋
- bzoj2437 [Noi2011]兔兔与蛋蛋
- bzoj 2437[Noi2011]兔兔与蛋蛋 黑白染色二分图+博弈+匈牙利新姿势
- 【BZOJ 2437】 2437: [Noi2011]兔兔与蛋蛋 (博弈+二分图匹配**)
- BZOJ 2437 兔兔与蛋蛋 (博弈论 二分图匹配)
- bzoj 2437 [Noi2011]兔子和鸡蛋 [二分图匹配]
- BZOJ2437 [Noi2011]兔兔与蛋蛋 【博弈论 + 二分图匹配】
- 【博弈+二分图匹配】[NOI2011]兔兔与蛋蛋游戏
- 【BZOJ2437】【codevs1949】兔兔与蛋蛋游戏,博弈+二分图匹配
- ★【二分图匹配】【博弈论】【NOI2011】兔兔和蛋蛋的游戏