• bzoj3504


    这是一道最大流的题目
    首先要引起注意的是,这类多个起点多个终点的问题一定要同时跑,不能分开来跑
    由于是无向图,也就相当于从起点跑2*n次
    好,不难想到s向两个起点连边,两终点想t连边,流量为2*an或2*bn
    然后对于每条危桥,正向反向连边,流量都为2,然后做最大流判断是否满流
    但是这样会出现两个问题,第一个如下的情况
    6 0 1 1 3 2 1
    XXXXOX
    XXXXXO
    XXXXOX
    XXXXXO
    OXOXXO
    XOXOOX
    不难发现中间有条边正向反向都被经过两次,而实际上是不允许的
    第二种情况时会出现a1只能b2,b1只能流向a2,这样做应该是不可行的,但实际会产生可行解
    解决的办法很简单,我们只要把b1,b2位置换一下,重新构图,再做一次最大流即可
    首先对于情况一,如果b1到b2必须多次经过某条边若干次,并且与a1到a2经过这条边反向
    那我们把b1b2调换后,就变成了经过双方都是同向经过,这样就只受到了一个流量限制
    而对于情况二,正确性是显然的
    于是我们就解决了这个问题

      1 const inf=200000007;
      2 type node=record
      3        point,next,flow:longint;
      4      end;
      5 
      6 var edge:array[0..200010] of node;
      7     a:array[0..51,0..51] of longint;
      8     pre,p,numh,cur,h,d:array[0..110] of longint;
      9     i,j,t,a1,a2,an,b1,b2,bn,n,len:longint;
     10     ch:char;
     11 
     12 function min(a,b:longint):longint;
     13   begin
     14     if a>b then exit(b) else exit(a);
     15   end;
     16 
     17 procedure add(x,y,f:longint);
     18   begin
     19     inc(len);
     20     edge[len].point:=y;
     21     edge[len].flow:=f;
     22     edge[len].next:=p[x];
     23     p[x]:=len;
     24   end;
     25 
     26 function sap:longint;
     27   var neck,u,i,j,tmp,q:longint;
     28   begin
     29     fillchar(h,sizeof(h),0);
     30     fillchar(numh,sizeof(numh),0);
     31     numh[0]:=t+1;
     32     for i:=0 to t do
     33       cur[i]:=p[i];
     34     u:=0;
     35     sap:=0;
     36     neck:=inf;
     37     while h[0]<t+1 do
     38     begin
     39      { writeln(u);
     40       readln;     }
     41       d[u]:=neck;
     42       i:=cur[u];
     43       while i<>-1 do
     44       begin
     45         j:=edge[i].point;
     46         if (edge[i].flow>0) and (h[u]=h[j]+1) then
     47         begin
     48           pre[j]:=u;
     49           cur[u]:=i;
     50           u:=j;
     51           neck:=min(edge[i].flow,neck);
     52           if u=t then
     53           begin
     54             sap:=sap+neck;
     55             while u<>0 do
     56             begin
     57               u:=pre[u];
     58               j:=cur[u];
     59               dec(edge[j].flow,neck);
     60               inc(edge[j xor 1].flow,neck);
     61             end;
     62             neck:=inf;
     63           end;
     64           break;
     65         end;
     66         i:=edge[i].next;
     67       end;
     68       if i=-1 then
     69       begin
     70         dec(numh[h[u]]);
     71         if numh[h[u]]=0 then exit;
     72         q:=-1;
     73         tmp:=t;
     74         i:=p[u];
     75         while i<>-1 do
     76         begin
     77           j:=edge[i].point;
     78           if edge[i].flow>0 then
     79             if h[j]<tmp then
     80             begin
     81               tmp:=h[j];
     82               q:=i;
     83             end;
     84           i:=edge[i].next;
     85         end;
     86         cur[u]:=q;
     87         h[u]:=tmp+1;
     88         inc(numh[h[u]]);
     89         if u<>0 then
     90         begin
     91           u:=pre[u];
     92           neck:=d[u];
     93         end;
     94       end;
     95     end;
     96   end;
     97 
     98 procedure work(x,y,f:longint);
     99   begin
    100     add(x,y,f);
    101     add(y,x,0);
    102   end;
    103 
    104 procedure build;
    105   var i,j:longint;
    106   begin
    107     fillchar(p,sizeof(p),255);
    108     len:=-1;
    109     for i:=1 to n do
    110       for j:=1 to n do
    111         if a[i,j]<>0 then work(i,j,a[i,j]);
    112   end;
    113 
    114 begin
    115   while not eof do
    116   begin
    117     readln(n,a1,a2,an,b1,b2,bn);
    118     inc(a1);
    119     inc(a2);
    120     inc(b1);
    121     inc(b2);
    122     fillchar(a,sizeof(a),0);
    123     t:=n+1;
    124     for i:=1 to n do
    125     begin
    126       for j:=1 to n do
    127       begin
    128         read(ch);
    129         if ch='O' then a[i,j]:=2
    130         else if ch='N' then a[i,j]:=inf;
    131       end;
    132       readln;
    133     end;
    134     build;
    135     work(0,a1,2*an);
    136     work(a2,t,2*an);
    137     work(0,b2,2*bn);
    138     work(b1,t,2*bn);
    139     if sap=2*(an+bn) then
    140     begin
    141       build;
    142       work(0,a1,2*an);
    143       work(a2,t,2*an);
    144       work(0,b1,2*bn);
    145       work(b2,t,2*bn);
    146       if sap=2*(an+bn) then writeln('Yes')
    147       else writeln('No');
    148     end
    149     else writeln('No');
    150   end;
    151 end.
    View Code
  • 相关阅读:
    2-分类
    1-确定变量间是否有关系—显著性检验
    git简单操作
    Hadoop HA和Hbase HA
    Docker入门操作
    内存数据库专题(MemCached 和Redis)
    Spark MLlib和Sprk GraphX
    Spark 调优
    Spark Streaming基础
    Spark SQL
  • 原文地址:https://www.cnblogs.com/phile/p/4473037.html
Copyright © 2020-2023  润新知