假设上界为 rrr, 下界为 lll
无源汇可行流(循环流)
法一:
建立源点 sss 和汇点 ttt , 对于图中每条边 <u,v><u, v><u,v> ,拆成如下三条:
- $<s,v> $ ,容量为 lll
- $<u,t> $ ,容量为 lll
- <u,v><u, v><u,v> ,容量为 r−lr - lr−l
其中前两条弧一般称为附加弧。
然后对图跑从 sss 到 ttt 的最大流,如果所有附加弧都满流,则有可行流。这时,每条非附加弧的流量加上它的容量下界,就是原图中这条弧应该有的流量。
法二:
建立源点 sss 和汇点 ttt ,对于每条边建立 <u,v><u,v><u,v> 容量为 r−lr-lr−l 的边。此外,对于图中每个点,令 $节点所有入流下界和节点所有出流下界和d[i] = \sum i节点所有入流下界和 - \sum i节点所有出流下界和 $ 。求 ddd 数组:若有一条 <u,v,L,R><u,v,L,R><u,v,L,R> 的边,令 d[u]−=L,d[v]+=Ld[u] -= L, d[v] += Ld[u]−=L,d[v]+=L 即可。
若 d[i]>0d[i] > 0d[i]>0, 建立 <s,i><s,i><s,i> 容量为 d[i]d[i]d[i] 的边。
若 d[i]<0d[i] < 0d[i]<0 ,建立 <i,t><i,t><i,t> 容量为 −d[i]-d[i]−d[i] 的边。
然后跑 sss 到 ttt 的最大流,若附加边全部满流,即 maxflow=∑d[i]>0maxflow = \sum d[i] >0maxflow=∑d[i]>0之和,存在可行流。每条边流量同法一。
有源汇可行流
从汇点 ttt 建立一条流向源点 sss 的边,上界为 infinfinf 下界为 000 ,就转化成了无源汇可行流。然后按照无源汇的判定方法建图即可,需要建立一个超级源点 SSSSSS 和超级汇点 TTTTTT .求原图中每条边对应的实际流量的方法,同无源汇可行流,只是忽略掉弧 <t,s><t,s><t,s> 就好。而且这时候弧 <t,s><t,s><t,s> 的流量就是原图的总流量。
有源汇最大流
判断有解方法如上说述。而且一定要先判是否有解。
如果存在可行流,那么在运行过有源汇可行流的图上(就是已经存在流量的那张图,流量不要清零),跑一遍从 sss 到 ttt 的最大流(这里的 sss 和 ttt 是原图的源和汇,不是附加超级源和附加超级汇),就是原图的最大流。
有源汇最小流
同上方法判断是否有解。求最小两种方法:
-
首先按照有源汇可行流的方法建模,但是不要建立<t,s><t,s><t,s>这条弧。
然后在这个图上,跑从附加源 ssssss 到附加汇 tttttt 的最大流。
这时候再添加弧 <t,s><t,s><t,s>,下界为 000,上界为 infinfinf。
在现在的这张图上,从 ssssss 到 tttttt 的最大流,就是原图的最小流。
理解方法:
我们前面提到过,有源汇可行流的流量只是对应一组可行流,并不是最大或者最小流。
并且在跑完有源汇可行流之后,弧<t,s><t,s><t,s>的流量就是原图的流量。
从这个角度入手,我们想让弧<t,s><t,s><t,s>的流量尽量小,就要尽量多的消耗掉那些“本来不需要经过<t,s><t,s><t,s>”的流量。
于是我们在添加<t,s><t,s><t,s>之前,跑一遍从 ssssss 到 tttttt 的最大流,就能尽量多的消耗那些流量了。
-
把最小流的初始值设为 TTT 到 SSS 这条边的流量,把 SSSSSS 连出去的边清掉,把 TTT 到 SSS 的边删掉,再在残量网络上跑一次 TTT 到 SSS 的最大流,初始最小流减去这次的最大流就是答案。