前言
因为我学得不深入,所以只能浅谈。强大的工具只要会用就行,并不需要很了解其中的原理(好比我用后缀自动机并不需要每次都把完全搞忘的原理复习一遍)。
提示:注意讲解中 s , t , s ′ , t ′ , s s , t t s,t,s',t',ss,tt s,t,s′,t′,ss,tt 的区别。
可行流
一般的网络流模型中每条边容量都有上界,而满足所有边内流量不超过上界、非源汇的点出入流量相等、源点出去的流量等于汇点流入的流量的一个流就是可行流。
这个应该没必要讲吧,学过普通网络流的都知道,所以不明白为什么脑瘫作者要设一个一级标题来说这个 。
注意最大流也是可行流,可行流不一定是最大流。当然,无下界时的0流也是可行流。
无源汇可行流
上面重申可行流的定义其实主要是为了强调:可行流不一定需要有源点汇点。
无源汇的可行流其实只需满足边内流量合法、每个点出入流量相等即可。
可是这也不需要搞一个大标题来说明吧。作者也太水了
无源汇有上下界可行流
巨佬的博客都是直接从这个开始讲的。居然不知道前面还有水的空间?
原本我们每条边的流量是由上界的,流量不能超过某个值,而现在我们规定每条边流量不能低于某个值,所以清楚点应该叫“有下界可行流”。
因为边的流量有下界,所以我们不妨假设所有边内初始就有下界这么多的流量,那么剩下能够流过的流量就是上界-下界, c i − l i c_i-l_i ci−li。这个时候的流唯一不满足的条件就是流量不平衡,每个点出入流量不相等。怎么调节呢?用网络流(废话)!
如果一个点流入流量的下界(就是所有入边的下界流量之和)
i
n
i
in_i
ini 大于流出流量的下界
o
u
t
i
out_i
outi,那么所有入边内至少需要额外的流量为0的流,而所有出边内至少需要额外的流量为
i
n
i
−
o
u
t
i
in_i-out_i
ini−outi 的流。
由于此时所有边已经默认流过了下界的流量,所以变成了下界为0、上界为原上界-原下界的边。出边内额外的流量并不能从入边里流入,所以需要新建一个源点 s s ss ss,从 s s ss ss 向 i i i 连一条容量为 i n i − o u t i in_i-out_i ini−outi 的边。
当 i n i < o u t i in_i<out_i ini<outi 的时候同理,入边内额外的流量不能从出边流出,我们需要建一个汇点 t t tt tt,从 i i i 向 t t tt tt 连一条容量为 o u t i − i n i out_i-in_i outi−ini 的边。
这个时候我们发现,原图存在可行流当且仅当从 s s ss ss 出去的边能够全部满流。观察建边过程可以发现, s s ss ss 出边容量的总和必然等于 t t tt tt 入边容量的总和,所以 s s ss ss 出边满流意味着 t t tt tt 入边满流,也就是原图上所有边需要的额外流量都能顺利地流过。
梳理一下流程:
- 建出网络,每条边容量为 c i − l i c_i-l_i ci−li,建立源汇点 s s ss ss、 t t tt tt;
- 统计每个点的出入流量下界 i n i in_i ini、 o u t i out_i outi,若 i n i > o u t i in_i>out_i ini>outi 则连边 s s → i ss\rightarrow i ss→i,容量为 i n i − o u t i in_i-out_i ini−outi;若 i n i < o u t i in_i<out_i ini<outi 则连边 i → t t i\rightarrow tt i→tt,容量为 o u t i − i n i out_i-in_i outi−ini;
- 从 s s ss ss 到 t t tt tt 跑一遍最大流;
- 若最大流不满流则无解,否则存在可行流,每条边的流量为当前网络中的流量+该边的下界流量。
有源汇有上下界可行流
搞懂了上面的操作,其它的就比较简单了。
有源汇的可行流与无源汇唯一的区别就是,源点和汇点的出入流量不相等(因为原则上源点没有流入流量,汇点没有流出流量),但是源点流出流量等于汇点流入流量。我们从汇点向源点连一条容量为 inf \inf inf 的边,那么就可以让“源点”、“汇点”也满足无源汇可行流的出入流量相等的条件,就可以转化为无源汇的可行流问题。
在有上下界的问题中,由于这条 t → s t\rightarrow s t→s 的边下界为0,所以在跑完一遍最大流后,该边的流量就等于源点到汇点的可行流的流量。
但是直接这么做是有问题的,因为原图上可能本来就有 t → s t\rightarrow s t→s 的边,这条边的分流会导致跑出来结果出问题。所以保险起见,我们需要新建源汇点 s ′ s' s′、 t ′ t' t′,从 s ′ s' s′ 向 s s s 连一条容量 inf \inf inf 的边, t t t 向 t ′ t' t′ 连一条容量 inf \inf inf 的边,然后原图的源汇点就变为了 s ′ s' s′、 t ′ t' t′,所以我们不再从 t t t 向 s s s 连 inf \inf inf 的边,而是从 t ′ t' t′ 向 s ′ s' s′ 连这条边。
有源汇有上下界最大流
注意,像最大流最小流这种东西必须要有源汇的情况下才能被定义。
有源汇上下界最大流其实非常简单,只需要在做完有源汇上下界可行流之后,把原图到 s s ss ss、 t t tt tt 的边去掉、把 t ′ t' t′ 到 s ′ s' s′ 的边去掉,然后从 s ′ s' s′ 到 t ′ t' t′ 增广,跑一遍最大流,那么答案就是该最大流流量+可行流的流量。因为增广的时候保证流量平衡,所以不会破坏掉之前跑上下界可行流做出的调整。
这个过程明显可以优化,我们不需要真的把原图到 s s ss ss、 t t tt tt 的边删掉,而是直接不管。因为连接 s s ss ss 和 t t tt tt 的边都已经满流,所以增广路不会经过它俩。
t ′ t' t′ 到 s ′ s' s′ 的那条边也是不需要删的。由于这条边上的流量等于可行流的流量,所以从 s ′ s' s′ 到 t ′ t' t′ 增广的时候必定会把这些流推回去,跑出来的最大流直接就是我们要求的答案。
有源汇有上下界最小流
在没有下界的时候,最小流就是0流。
有源汇上下界最小流其实就和最大流差不多,在做完有源汇上下界可行流之后,把 t ′ t' t′ 到 s ′ s' s′ 的边去掉,然后从 t ′ t' t′ 到 s ′ s' s′ 倒着增广,相当于退流,答案就是可行流流量-最大流流量。
这个时候没法省, t ′ t' t′ 到 s ′ s' s′ 这条边必须去掉,否则跑出来的最大流为 inf \inf inf,答案直接为负。
至于有源汇有上下界·最大/最小费用·最大/最小流,原理类似,我就不赘述了。我根本打不来这个
例题
Reactor Cooling 无源汇有上下界可行流板题
Flow construction 有源汇有上下界最小流
Budget 有源汇有上下界可行流
Inspection 有源汇有(上)下界最小流
BZOJ 矩阵 二分答案、有源汇有上下界可行流