首先对网格染色,发现是而二分图。
那么即在二分图上选一个起点走过的点无法再走,最后无路可走就输了。
如果起点必在最大匹配中,先手必赢。
如果起点不一定在最大匹配中(包括不可能在),后手必赢。网上有解释。
因为写二分图不怎么熟练,所以还是用网络流吧。
找的就是可行的和不在最大匹配中点。建边要用单向边。
从源点和汇点开始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++
时间: 2024-10-09 18:49:38