【BZOJ1443】游戏Game(JSOI2009)-二分图最大匹配+博弈
2017-06-08 12:24
453 查看
测试地址:游戏Game
做法:这一题的思想十分巧妙……这是一道披着博弈皮的二分图匹配题啊……
这一题需要用到二分图最大匹配+博弈。
首先我们注意到,如果将矩形黑白间隔染色,那么矩形上任何一条边都连接黑白两色的点,这启发我们把矩阵转化成二分图进行处理。然后我们研究什么样的起点才能保证后手必胜(这里称先走的为先手)。
显然,如果二分图存在完备匹配,那么后手必败,因为先手只需要按着匹配边走,就可以把后手卡死,那么反之,如果二分图不存在完备匹配,那么一定存在一个起点使得后手必胜。那么这样的点有什么性质呢?先说结论:如果存在一个最大匹配不包含某点,那么这个点就是使得后手必胜的点。证明如下:先手从左侧某点走出时,可能走到匹配点或非匹配点,如果走到匹配点,那么后手就走匹配边即可,如果走到非匹配点,那么起点走到这个点的路径就是一条增广路,这显然与最大匹配的前提矛盾,那么这样一直走下去,先手一定会被卡死,综上所述,以这样的点作为起点则后手必胜。那么现在问题就变成了怎么找这样的点。
有的同学可能会想,我们做一次最大匹配,把没有覆盖到的点直接输出不就好了吗?注意我上面说的,我们要找的点是“存在一个最大匹配不包含的”,而最大匹配可能有很多,那么要怎么办呢?我们可以做两次最大匹配,每次只考虑二分图的一侧上有没有可能的起点,那么我们可以这样做:首先做一次最大匹配,然后把没被覆盖到的点放进队列,然后每个点可以扩展到另一侧的匹配点,那么这些匹配点所对应的一侧上的点就也是答案,再把这些点放进队列。为什么这样做是对的呢?注意到我们如果按照以上走法,走过的路径应该是一条类似增广路的路径,只不过非匹配边和匹配边数量相等,那么我们把非匹配边换成匹配边,把匹配边换成非匹配边,匹配数是不变的,这样变换之后还是一个最大匹配,但是这样的话走到的点就会变成非匹配点,那么和条件“存在一个最大匹配不包含”相符,所以这个点也是答案。这样我们就解决了这一问题。
做二分图最大匹配时,匈牙利算法的时间复杂度是平方级的,虽然看上去有10000个点跑不过,但是匈牙利算法常数很小,而且搭配这个图的特殊性,常数就更小了,所以时间是不用担心的,亲测可过。
以下是本人代码:
做法:这一题的思想十分巧妙……这是一道披着博弈皮的二分图匹配题啊……
这一题需要用到二分图最大匹配+博弈。
首先我们注意到,如果将矩形黑白间隔染色,那么矩形上任何一条边都连接黑白两色的点,这启发我们把矩阵转化成二分图进行处理。然后我们研究什么样的起点才能保证后手必胜(这里称先走的为先手)。
显然,如果二分图存在完备匹配,那么后手必败,因为先手只需要按着匹配边走,就可以把后手卡死,那么反之,如果二分图不存在完备匹配,那么一定存在一个起点使得后手必胜。那么这样的点有什么性质呢?先说结论:如果存在一个最大匹配不包含某点,那么这个点就是使得后手必胜的点。证明如下:先手从左侧某点走出时,可能走到匹配点或非匹配点,如果走到匹配点,那么后手就走匹配边即可,如果走到非匹配点,那么起点走到这个点的路径就是一条增广路,这显然与最大匹配的前提矛盾,那么这样一直走下去,先手一定会被卡死,综上所述,以这样的点作为起点则后手必胜。那么现在问题就变成了怎么找这样的点。
有的同学可能会想,我们做一次最大匹配,把没有覆盖到的点直接输出不就好了吗?注意我上面说的,我们要找的点是“存在一个最大匹配不包含的”,而最大匹配可能有很多,那么要怎么办呢?我们可以做两次最大匹配,每次只考虑二分图的一侧上有没有可能的起点,那么我们可以这样做:首先做一次最大匹配,然后把没被覆盖到的点放进队列,然后每个点可以扩展到另一侧的匹配点,那么这些匹配点所对应的一侧上的点就也是答案,再把这些点放进队列。为什么这样做是对的呢?注意到我们如果按照以上走法,走过的路径应该是一条类似增广路的路径,只不过非匹配边和匹配边数量相等,那么我们把非匹配边换成匹配边,把匹配边换成非匹配边,匹配数是不变的,这样变换之后还是一个最大匹配,但是这样的话走到的点就会变成非匹配点,那么和条件“存在一个最大匹配不包含”相符,所以这个点也是答案。这样我们就解决了这一问题。
做二分图最大匹配时,匈牙利算法的时间复杂度是平方级的,虽然看上去有10000个点跑不过,但是匈牙利算法常数很小,而且搭配这个图的特殊性,常数就更小了,所以时间是不用担心的,亲测可过。
以下是本人代码:
#include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int n,m,tot=0,first[10010]={0},q[10010]={0},vis[10010]={0},h,t; int l[5010]={0},r[5010]={0},mat[10010],maxmat; char s[110][110]; bool ans[10010]={0}; struct edge {int v,next;} e[50010]; void insert(int a,int b) { e[++tot].v=b,e[tot].next=first[a],first[a]=tot; e[++tot].v=a,e[tot].next=first[b],first[b]=tot; } bool find_match(int v,int p) { vis[v]=p; for(int i=first[v];i;i=e[i].next) { if (mat[e[i].v]==-1) { mat[e[i].v]=v; mat[v]=e[i].v; return 1; } else if (vis[mat[e[i].v]]!=p&&find_match(mat[e[i].v],p)) { mat[e[i].v]=v; mat[v]=e[i].v; return 1; } } return 0; } void find_answer() { for(int i=h;i<=t;i++) vis[q[i]]=1; while(h<=t) { int v=q[h]; ans[v]=1; for(int i=first[v];i;i=e[i].next) if (mat[e[i].v]!=-1&&!vis[mat[e[i].v]]) { vis[mat[e[i].v]]=1; q[++t]=mat[e[i].v]; } h++; } } void hungary(bool mode) { maxmat=0; memset(mat,-1,sizeof(mat)); memset(vis,0,sizeof(vis)); h=1,t=0; if (!mode) { for(int i=1;i<=l[0];i++) if (mat[l[i]]==-1) if (find_match(l[i],i)) maxmat++; for(int i=1;i<=l[0];i++) if (mat[l[i]]==-1) q[++t]=l[i]; } else { for(int i=1;i<=r[0];i++) if (mat[r[i]]==-1) if (find_match(r[i],i)) maxmat++; for(int i=1;i<=r[0];i++) if (mat[r[i]]==-1) q[++t]=r[i]; } memset(vis,0,sizeof(vis)); find_answer(); } int main() { scanf("%d%d",&n,&m); for(int i=0;i<n;i++) scanf("%s",s[i]); for(int i=0;i<n;i++) for(int j=0;j<m;j++) { if (s[i][j]=='#') continue; if ((i+j)%2==0) l[++l[0]]=i*m+j; else r[++r[0]]=i*m+j; if (j>0&&s[i][j-1]=='.') insert(i*m+j-1,i*m+j); if (i>0&&s[i-1][j]=='.') insert((i-1)*m+j,i*m+j); } hungary(0); if (maxmat==l[0]&&maxmat==r[0]) {printf("LOSE");return 0;} hungary(1); printf("WIN\n"); for(int i=0;i<n*m;i++) if (ans[i]) printf("%d %d\n",i/m+1,i%m+1); return 0; }
相关文章推荐
- 【bzoj1443】【JSOI2009】【游戏game】【二分图博弈】
- bzoj1443 [JSOI2009]游戏Game 二分图 博弈
- 【BZOJ1443】【JSOI2009】游戏Game 二分图+博弈
- [二分图博弈] BZOJ 1443 [JSOI2009]游戏Game & BZOJ 2437 [Noi2011]兔兔与蛋蛋
- [BZOJ]1443 [JSOI2009]游戏Game 二分图+博弈
- BZOJ 1443 JSOI2009 游戏Game 二分图博弈
- Bzoj - 1443 [JSOI2009]游戏Game [二分图博弈]
- bzoj 1443: [JSOI2009]游戏Game (二分图博弈+网络流)
- bzoj 1443: [JSOI2009]游戏Game 二分图博弈
- BZOJ 1443 [JSOI2009]游戏Game
- BZOJ:1443: [JSOI2009]游戏Game
- BZOJ 1443: [JSOI2009]游戏Game
- BZOJ 1443: [JSOI2009]游戏Game
- BZOJ1443: [JSOI2009]游戏Game
- BZOJ1443: [JSOI2009]游戏Game
- 【BZOJ】1443: [JSOI2009]游戏Game
- bzoj1443 [JSOI2009]游戏Game
- bzoj1443 [JSOI2009]游戏Game
- bzoj1443 [JSOI2009]游戏Game
- BZOJ 1443 [JSOI2009]游戏Game | UVALive 5882 Racing Car Trail