题意:
给n个点,及m根pipe,每根pipe用来流躺液体的,单向的,每时每刻每根pipe流进来的物质要等于流出去的物质,要使得m条pipe组成一个循环体,里面流躺物质。
并且满足每根pipe一定的流量限制,范围为[Li,Ri].即要满足每时刻流进来的不能超过Ri(最大流问题),同时最小不能低于Li。
n<=200
思路:
From HZWER
上界用ci表示,下界用bi表示。
下界是必须流满的,那么对于每一条边,去掉下界后,其自由流为ci– bi。
主要思想:每一个点流进来的流=流出去的流
对于每一个点i,令
Mi= sum(i点所有流进来的下界流)– sum(i点所有流出去的下界流)
如果Mi大于0,代表此点必须还要流出去Mi的自由流,那么我们从源点连一条Mi的边到该点。
如果Mi小于0,代表此点必须还要流进来Mi的自由流,那么我们从该点连一条Mi的边到汇点。
如果求S->T的最大流,看是否满流(S的相邻边都流满)。
满流则有解,否则无解。
以下是我的理解,用来说明算法的正确性:
首先不能根据给定的条件直接建图,因为不满足流量平衡
于是我们建立一些从源点连出与连入汇点的辅助边使平衡成立
但最终方案如果还是需要辅助边的话就说明无法调整原来的流量使平衡成立
所以只需要判断源点(我觉得汇点也应该判断,但只判源点也能过)相连的边上如果还有流量就无法构造出一组可行解
1 var head,vet,next,len,fan,a:array[1..210000]of longint; 2 gap:array[0..500]of longint; 3 dis,sum:array[1..500]of longint; 4 n,m,i,j,x,y,z,tot,source,src,s,cas,v:longint; 5 6 procedure add(a,b,c:longint); 7 begin 8 inc(tot); 9 next[tot]:=head[a]; 10 vet[tot]:=b; 11 len[tot]:=c; 12 head[a]:=tot; 13 14 inc(tot); 15 next[tot]:=head[b]; 16 vet[tot]:=a; 17 len[tot]:=0; 18 head[b]:=tot; 19 end; 20 21 function min(x,y:longint):longint; 22 begin 23 if x<y then exit(x); 24 exit(y); 25 end; 26 27 function dfs(u,aug:longint):longint; 28 var e,v,t,val,flow:longint; 29 begin 30 if u=src then exit(aug); 31 e:=head[u]; flow:=0; val:=s-1; 32 while e<>0 do 33 begin 34 v:=vet[e]; 35 if len[e]>0 then 36 begin 37 if dis[u]=dis[v]+1 then 38 begin 39 t:=dfs(v,min(aug-flow,len[e])); 40 len[e]:=len[e]-t; 41 len[fan[e]]:=len[fan[e]]+t; 42 flow:=flow+t; 43 if dis[source]>=s then exit(flow); 44 if aug=flow then break; 45 end; 46 val:=min(val,dis[v]); 47 end; 48 e:=next[e]; 49 end; 50 if flow=0 then 51 begin 52 dec(gap[dis[u]]); 53 if gap[dis[u]]=0 then dis[source]:=s; 54 dis[u]:=val+1; 55 inc(gap[dis[u]]); 56 end; 57 exit(flow); 58 end; 59 60 function maxflow:longint; 61 var ans:longint; 62 begin 63 fillchar(gap,sizeof(gap),0); 64 fillchar(dis,sizeof(dis),0); 65 gap[0]:=s; ans:=0; 66 while dis[source]<s do ans:=ans+dfs(source,maxlongint); 67 exit(ans); 68 end; 69 70 function isok:boolean; 71 var u,e:longint; 72 begin 73 u:=source; e:=head[u]; 74 while e<>0 do 75 begin 76 if len[e]>0 then exit(false); 77 e:=next[e]; 78 end; 79 exit(true); 80 end; 81 82 begin 83 assign(input,'zoj2314.in'); reset(input); 84 assign(output,'zoj2314.out'); rewrite(output); 85 readln(cas); 86 for i:=1 to 210000 do 87 if i and 1=1 then fan[i]:=i+1 88 else fan[i]:=i-1; 89 for v:=1 to cas do 90 begin 91 for i:=1 to s do head[i]:=0; 92 for i:=1 to n do sum[i]:=0; 93 s:=0; tot:=0; 94 read(n,m); 95 for i:=1 to m do 96 begin 97 read(x,y,a[i],z); 98 sum[y]:=sum[y]+a[i]; 99 sum[x]:=sum[x]-a[i]; 100 add(x,y,z-a[i]); 101 end; 102 source:=n+1; src:=n+2; s:=n+2; 103 for i:=1 to n do 104 if sum[i]<0 then add(i,src,-sum[i]) 105 else add(source,i,sum[i]); 106 source:=n+1; src:=n+2; s:=n+2; 107 maxflow; 108 if isok then 109 begin 110 writeln('YES'); 111 for i:=1 to m do writeln(a[i]+len[i<<1]); 112 end 113 else writeln('NO'); 114 writeln; 115 end; 116 close(input); 117 close(output); 118 end.