我决定继续我的学术+数学风格,这种风格虽然有点难理解,但是定义精确,而且往往能反映出更多的性质,比语言描述往往更为简洁。
好吧,我们继续我们的网络流的介绍。考虑一个有向图
G=(V,E)
,其源点为
s
,汇点为
如果再考虑另一个例子,比如说现在我们有无限多的货物要通过一个公路系统,公路系统上没一条路都有一个容量限制,同时还有收费站,每一吨货物都要收费若干元(而且每一条路上的费用不一定相同),那么同样,我们也只能从起点
s
运一些货物到终点
用神奇的数学方法描述成线性规划的形式,就是像下面这样:
其中, ci 表示第 i 条边的最大流量,那么这个模型就很容易被看出了。
从上面这一大块式子可以看出一个流的三个特性:
- 流量平衡:
∑(i,v)∈Ef(u,i)=∑(u,i)∈Ef(i,v) - 容量限制: f(i,j)≤c(i,j)
反对称性: f(i,j) = -f(j,i)
上述的三个特性都很好理解。比如对于流量平衡,就是对于一个点而言,进去多少流量,也出来多少流量。而容量限制前面已经提到过,就是某一条边上流过的流量不应超过其的最大流量,反对称性这一条件则有点数学的味道,就像“减去 5 ”等价于“加上
−5 ”一样,就是定义了一种负流量的概念,也就是流过去多少流量,等价于留回来负的流量,这和流量平衡条件结合一下就很好理解了。好的,那么最大流怎么求?证明在这里略去,反正我们先上算法。首先是一个定理,以帮助我们理解。倘若我们现在有一个有向图 G={V,E} ,然后定义 f(u,v) 表示边 (u,v)∈E 的流量,另外 s,t∈V 分别是整个图的起点和终点,那么,我们便有了一个神奇的定理:
- 不断增广
s−t
最短路(也就是使得这条路上通过的流量尽量大),那么最多只需要
O(|V||E|)
次迭代就可以求出最大流。
关于这个定理的实现有很多。比如说,我们如果直接用BFS/DFS求最短路,然后再直接增广,那么容易考虑到其时间复杂度为 O(nm2) ,也就是Ford-Fulkerson算法。
当然,F-F算法还有一个要点,就是反向边。考虑一种“撤销”操作,令得流过去的流可以在某种意义上“流回来”,这样才正确。如果没有的话,那么算法就会“一条路走到黑”,陷入局部困境。
那么,有什么优化的方法吗?Ford-Fulkerson的时间复杂度太高了,有什么方法优化么?有!
考虑到Ford-Fulkerson有一个瓶颈实际上在求最短路上,那么我们可以先构造一种叫层次图的东西,使得所有的s-t路径都是s-t最短路,那么我们就只需增广这个层次图中每一条路径所对应的边,然后再不断重构层次图就好了。
考虑这样一种层次图的构建方法,也就是设 h(i) 为点 i 到源点s 的最短距离,然后只增广满足 h(v)=h(u)+1 条件的边 (u,v)∈E 就好了。
在考虑一下这样做的时间复杂度。每一次的增广,距离至少增加 1 ,然后距离最大为n−1 ,而一共需 O(nm) 次的迭代,于是总共的时间复杂度也就是 O(n2m) 。
另外还有更快的做法,无论是在理论时间复杂度上,还是实际上,都各有胜过它的代码。
但是,Dinic短啊!