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