bzoj1443

首先要思考的问题肯定是,什么点可以是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.
View Code
原文地址:https://www.cnblogs.com/phile/p/4473214.html