BZOJ 1433 二分图上的博弈

Posted on 2016-05-12 22:48  yyjxx2010xyu  阅读(167)  评论(0编辑  收藏  举报

首先对网格染色,发现是而二分图。

那么即在二分图上选一个起点走过的点无法再走,最后无路可走就输了。

如果起点必在最大匹配中,先手必赢。
如果起点不一定在最大匹配中(包括不可能在),后手必赢。网上有解释。
因为写二分图不怎么熟练,所以还是用网络流吧。
找的就是可行的和不在最大匹配中点。建边要用单向边。
从源点和汇点开始Dfs。假如从左边开始那么先扫到右边后又扫到左边。那么那个点就是可行点。
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <algorithm>
  5 using namespace std;
  6 const int Maxn=10010;
  7 const int Inf=0x3f3f3f3f;
  8 int n,m,S,T,g[110][110],Color[Maxn],head[Maxn],Level[Maxn],Q[Maxn],u,v,cnt,cur[Maxn],Ans[Maxn],ans;
  9 bool vis[Maxn];
 10 struct Node{int to,next,w;}edge[1000010];
 11 const int dx[4]={0,0,1,-1};
 12 const int dy[4]={1,-1,0,0};
 13 inline int Id(int x,int y) {return (x-1)*m+y;}
 14 inline bool Check(int u,int v) {return ((u<=n&&u>=1)&&(v<=m&&v>=1));}
 15 inline int Min(int x,int y) {return x>y?y:x;}
 16 inline void ADD(int u,int v,int w)
 17 {edge[cnt].to=v;edge[cnt].next=head[u];edge[cnt].w=w;head[u]=cnt++;}
 18 inline void Add(int u,int v,int w) {ADD(u,v,w);ADD(v,u,0);}
 19 bool Bfs()
 20 {
 21     memset(Level,-1,sizeof(Level));
 22     Level[S]=0; Q[1]=S; int l=1,r=1;
 23     while (l<=r)
 24     {
 25         int u=Q[l++];
 26         for (int i=head[u];i!=-1;i=edge[i].next)
 27             if (Level[edge[i].to]==-1 && edge[i].w>0)
 28             {
 29                 Level[edge[i].to]=Level[u]+1;
 30                 Q[++r]=edge[i].to;
 31             }
 32     }
 33     if (Level[T]==-1) return false;
 34     return true;
 35 }
 36 int Find(int u,int low)
 37 {
 38     if (u==T || low==0) return low;
 39     int cap=0;
 40     for (int i=cur[u];i!=-1;i=edge[i].next)
 41         if (edge[i].w>0 && Level[edge[i].to]==Level[u]+1)
 42         {
 43             int tmp=Find(edge[i].to,Min(low,edge[i].w));
 44             if (tmp==0) continue;
 45             low-=tmp,cap+=tmp;
 46             edge[i].w-=tmp,edge[i^1].w+=tmp;
 47             if (edge[i].w>0) cur[u]=i;
 48         }
 49     if (cap) return cap;
 50     Level[u]=-1;
 51     return 0;
 52 }
 53 void Dfs(int u,int c)
 54 {
 55     vis[u]=true;
 56     if (Color[u]==c && u!=S && u!=T) Ans[++ans]=u;
 57     for (int i=head[u];i!=-1;i=edge[i].next)
 58         if (edge[i].w==c && !vis[edge[i].to]) Dfs(edge[i].to,c);
 59 }
 60  
 61 void Get_Ans()
 62 {
 63     memset(vis,false,sizeof(vis)),Dfs(S,1);
 64     memset(vis,false,sizeof(vis)),Dfs(T,0);
 65 }
 66 int main()
 67 {
 68     // freopen("c.in","r",stdin);
 69     // freopen("c.out","w",stdout);
 70     scanf("%d%d",&n,&m);
 71     for (int i=1;i<=n;i++)
 72         for (int j=1;j<=m;j++)
 73         {
 74             char ch=getchar();
 75             while (ch!='.' && ch!='#') ch=getchar();
 76             if (ch=='.') g[i][j]=1;
 77             if (ch=='#') g[i][j]=0;
 78         }
 79     S=0,T=Id(n,m)+1;
 80     memset(head,-1,sizeof(head));
 81     for (int i=1;i<=n;i++)
 82         for (int j=1;j<=m;j++)
 83             if (g[i][j])
 84             {
 85                 if (!((i+j)&1)) 
 86                 {
 87                     Add(S,Id(i,j),1);
 88                     Color[Id(i,j)]=true;
 89                     for (int k=0;k<4;k++)
 90                     {
 91                         int u=i+dx[k],v=j+dy[k];
 92                         if (!Check(u,v)) continue;
 93                         if (g[u][v]) Add(Id(i,j),Id(u,v),1);
 94                     }
 95                 }
 96                 else Add(Id(i,j),T,1);
 97             }
 98     // for (int i=0;i<cnt;i++) printf("%d ",edge[i].to); puts("");
 99     // for (int i=0;i<cnt;i++) printf("%d ",edge[i].w);puts("");
100     // for (int i=1;i<cnt;i++) printf("%d ",edge[i].next);puts("");
101     while (Bfs())
102     {
103         for (int i=S;i<=T;i++) cur[i]=head[i];
104         Find(S,Inf);
105     }
106     Get_Ans();
107     if (!ans) puts("LOSE"); else
108     {
109         puts("WIN");
110         sort(Ans+1,Ans+ans+1);
111         for (int i=1;i<=ans;i++) printf("%d %d\n",(Ans[i]-1)/m+1,(Ans[i]-1)%m+1);
112     }
113     // if ()
114     return 0;   
115 }
C++