更多文章可以在本人的个人小站:https://kaiserwilheim.github.io 查看。
转载请注明出处。
(3-13至3-14重修)
(6-23至6-24增添上下界网络流相关内容)
什么是网络流
网络流是指在网络(或者流网络, Flow Network )中的流。
网络
网络是指一个有向图 G = ( V , E ) G=(V,E) G=(V,E)。
每条边 ( u , v ) ∈ E (u,v)\in E (u,v)∈E 都有一个权值 c ( u , v ) c(u,v) c(u,v),称之为容量(Capacity),当 ( u , v ) ∉ E (u,v)\notin E (u,v)∈/E 时有 c ( u , v ) = 0 c(u,v)=0 c(u,v)=0。
其中有两个特殊的点:源点(Source) s ∈ V s\in V s∈V 和汇点(Sink) t ∈ V , ( s ≠ t ) t\in V,(s\neq t) t∈V,(s=t)。
流
设 f ( u , v ) f(u,v) f(u,v) 定义在二元组 ( u ∈ V , v ∈ V ) (u\in V,v\in V) (u∈V,v∈V) 上的实数函数且满足
- 容量限制:对于每条边,流经该边的流量不得超过该边的容量,即, f ( u , v ) ≤ c ( u , v ) f(u,v)\leq c(u,v) f(u,v)≤c(u,v)
- 斜对称性:每条边的流量与其相反边的流量之和为 0,即 f ( u , v ) = − f ( v , u ) f(u,v)=-f(v,u) f(u,v)=−f(v,u)
- 流守恒性:从源点流出的流量等于汇点流入的流量,即 ∀ x ∈ V − { s , t } , ∑ ( u , x ) ∈ E f ( u , x ) = ∑ ( x , v ) ∈ E f ( x , v ) \forall x\in V - \lbrace s,t \rbrace , \sum_{(u,x) \in E} f(u,x) = \sum_{(x,v) \in E} f(x,v) ∀x∈V−{ s,t},∑(u,x)∈Ef(u,x)=∑(x,v)∈Ef(x,v)
那么 f f f 称为网络 G G G 的流函数。对于 ( u , v ) ∈ E (u,v)\in E (u,v)∈E, f ( u , v ) f(u,v) f(u,v) 称为边的流量, c ( u , v ) − f ( u , v ) c(u,v)-f(u,v) c(u,v)−f(u,v) 称为边的剩余容量。整个网络的流量为 ∑ ( s , v ) ∈ E f ( s , v ) \sum_{(s,v)\in E}f(s,v) ∑(s,v)∈Ef(s,v),即从源点发出的所有流量之和。
一般而言也可以把网络流理解为整个图的流量。而这个流量必满足上述三个性质。
流函数的完整定义为
f ( u , v ) = { f ( u , v ) , ( u , v ) ∈ E , − f ( v , u ) , ( v , u ) ∈ E , 0 , ( u , v ) ∉ E , ( v , u ) ∉ E . f(u,v)= \begin{cases} f(u,v), & (u,v) \in E, \\\\ -f(v,u), & (v,u) \in E, \\\\ 0, & (u,v) \not\in E , (v,u) \not\in E. \end{cases} f(u,v)=⎩⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎧f(u,v),−f(v,u),0,(u,v)∈E,(v,u)∈E,(u,v)∈E,(v,u)∈E.
反向边
反向边是网络流中很重要的一类边。
一般的时候,在题目给定的流网络中是不包含有关反向边的信息的,我们画图的时候也一般不将反向边画出来。
但是,反向边可以利用流网络的一些性质,通过对其流量进行操作,使得我们的子程序可以经由其进行反悔的操作。
建立反向边的时候可以使用一些小trick。
我们如果使用邻接表(或称链式前向星)来建图的话,可以选择同时建正向边和反向边,并使边的编号从0开始,从而可以通过使用异或操作来访问当前边的反向边。
网络流的常见问题
网络流问题中常见的有以下三种:最大流,最小割,费用流。
解决网络流问题的难点不是算法或者代码,而是建图。对于大多数的网络流题目,我们需要仔细分辨琢磨才可以知道如何将问题转换为网络流这几种问题的其中一种或几种,并将题目中的限制用边/点的限制体现出来。
最大流
简介
对于一个给定的网络,其合法的流函数其实有很多。其中使得整个网络的流量最大的流函数被称为网络的最大流。
求解一个网络的最大流其实有很多用处,例如可以将二分图的最大匹配问题转化为求解最大流。
求解最大流的算法有很多种,比如Ford-Fulkerson增广路算法、Push-Relable预流推进算法等等。
实际上,最常用的还是Ford-Fulkerson增广路算法中的EK和Dinic两种。
Ford-Fulkerson 增广路算法
该方法通过寻找增广路来更新最大流,有EK,dinic,SAP,ISAP等主流算法。
求解最大流之前,我们先认识一些概念。
残量网络
首先我们介绍一下一条边的剩余容量 c f ( u , v ) c_f(u,v) cf(u,v)(Residual Capacity),它表示的是这条边的容量与流量之差,即 c f ( u , v ) = c ( u , v ) − f ( u , v ) c_f(u,v) = c(u,v) - f(u,v) c