zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    C#-MessageBox全部函数重载形式及举例
    在软件开发中应用80:20原则
    C# 程序员最常犯的 10 个错误
    关于vs2013调试的偶然错误发现与总结(vs2013的承载进程)---ShinePans
    C#好书盘点
    C#中 父类与子类相互强制转换之实验
    如何用C#语言构造蜘蛛程序
    C#创建word,操作、读写
    Linux less/more命令详解
    Linux 环境变量详解
  • 原文地址:https://www.cnblogs.com/phile/p/4473214.html
Copyright © 2011-2022 走看看