这是一道最大流的题目
首先要引起注意的是,这类多个起点多个终点的问题一定要同时跑,不能分开来跑
由于是无向图,也就相当于从起点跑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

 

posted on 2015-01-09 22:27  acphile  阅读(206)  评论(0编辑  收藏  举报