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