首先要思考的问题肯定是,什么点可以是ans,
不难想到对图黑白染色,假如一个棋子不管怎么走,都只能走到和它同色的点上时,这就是一个ans
再考虑,每次棋子的移动都是黑白相间的
再考虑,黑白染色是可以构成一个二分图的
不难想到,二分图上的增广路。
于是第一问就很好解决,我们构建二分图做最大匹配,
如果所有的黑点和白点都匹配了,那么一定不存在,否则一定存在。
为什么呢?
我们知道,如果这个匹配是二分图的最大匹配,那么图中一定不存在增广路;
而增广路是指从非匹配边最终走到非匹配边(非匹配边比匹配边数多1);
假存在一个未被匹配的点,那么小AA将棋子放在这个点上,
那么下一步小YY要么没法走,要么只能走到一个匹配过的点上,走了一条非匹配边。
那么小AA这要走这个点的匹配边,那下一步小YY要么没法走,要么只能走一条非匹配边
这样下去,我们知道是不存在增广路的,那么最后一步一定走的是匹配边——即小AA走最后一步
所以,只要最大匹配中存在未匹配点,那么这个点就是答案之一;
那答案是不是只有这些点呢?
不是,因为最大匹配不止一种,可以有其他点在最大匹配中未被匹配;
考虑到这样一种情况,我们从一个未匹配点k出发,如果走到了一个被匹配点i,记i原来匹配的点为j
如果我们仅仅改变让i和k匹配,而不和j匹配,那么这样并没有改变最大匹配的数目,而又找到了一个新的点他可以不被匹配
那么这个点显然也是ans
所以,我们做完最大匹配后,我们只要从未被匹配点按未匹配边,匹配边相间dfs下去,找到的所有和起点属于同一点集的点也是ans,问题得解
1 const dx:array[1..4] of integer=(0,0,-1,1); 2 dy:array[1..4] of integer=(1,-1,0,0); 3 type node=record 4 point,next:longint; 5 end; 6 7 var a:array[0..110,0..110] of longint; 8 edge:array[0..2001000] of node; 9 ty,p,cx,cy,wx,wy:array[0..10010] of longint; 10 v:array[0..10010] of boolean; 11 k,len,x,y,i,j,n,m,w,r,t:longint; 12 s:string; 13 14 procedure add(x,y:longint); 15 begin 16 inc(len); 17 edge[len].point:=y; 18 edge[len].next:=p[x]; 19 p[x]:=len; 20 end; 21 22 function find(x:longint):longint; //匈牙利 23 var i,y:longint; 24 begin 25 i:=p[x]; 26 while i<>-1 do 27 begin 28 y:=edge[i].point; 29 if not v[y] then 30 begin 31 v[y]:=true; 32 if (cy[y]=-1) or (find(cy[y])=1) then 33 begin 34 cx[x]:=y; 35 cy[y]:=x; 36 exit(1); 37 end; 38 end; 39 i:=edge[i].next; 40 end; 41 exit(0); 42 end; 43 44 procedure dfsx(x:longint); 45 var i,y:longint; 46 begin 47 v[x]:=true; 48 i:=p[x]; 49 while i<>-1 do 50 begin 51 y:=edge[i].point; 52 if (cy[y]<>-1) and not v[cy[y]] then dfsx(cy[y]); 53 i:=edge[i].next; 54 end; 55 end; 56 57 procedure dfsy(y:longint); 58 var i,x:longint; 59 begin 60 v[y]:=true; 61 i:=p[y]; 62 while i<>-1 do 63 begin 64 x:=edge[i].point; 65 if (cx[x]<>-1) and not v[cx[x]] then dfsy(cx[x]); 66 i:=edge[i].next; 67 end; 68 end; 69 70 begin 71 fillchar(p,sizeof(p),255); 72 readln(n,m); 73 for i:=1 to n do 74 begin 75 readln(s); 76 for j:=1 to m do 77 if s[j]='.' then 78 begin 79 inc(k); 80 a[i,j]:=k; 81 wx[k]:=i; 82 wy[k]:=j; 83 ty[k]:=(i+j) mod 2; //划分点集 84 end; 85 end; 86 r:=k; 87 for i:=1 to n do 88 for j:=1 to m do 89 if ((i+j) mod 2=0) and (a[i,j]>0) then 90 begin 91 inc(t); 92 for k:=1 to 4 do 93 begin 94 x:=i+dx[k]; 95 y:=j+dy[k]; 96 if a[x,y]>0 then 97 begin 98 add(a[i,j],a[x,y]); 99 add(a[x,y],a[i,j]); 100 end; 101 end; 102 end; 103 fillchar(cx,sizeof(cx),255); 104 fillchar(cy,sizeof(cy),255); 105 106 for i:=1 to r do 107 if (cx[i]=-1) and (ty[i]=0) then 108 begin 109 fillchar(v,sizeof(v),false); 110 w:=w+find(i); 111 end; 112 if (w=t) and (r-t=t) then 113 begin 114 writeln('LOSE'); 115 halt; 116 end; 117 writeln('WIN'); 118 fillchar(v,sizeof(v),false); 119 for i:=1 to r do 120 if (cx[i]=-1) and (ty[i]=0) then dfsx(i); 121 for i:=1 to r do 122 if (cy[i]=-1) and (ty[i]=1) then dfsy(i); 123 for i:=1 to r do 124 if v[i] then writeln(wx[i],' ',wy[i]); 125 end.