文档章节

网络流各类算法简单总结与比较

o
 osc_x4h57ch8
发布于 2018/04/24 11:15
字数 2920
阅读 10
收藏 0

精选30+云产品,助力企业轻松上云!>>>

信息学竞赛的算法理论分析是个深海,趁着没掉进去,写个总结,然后赶紧去刷题...

本人不是OI选手且对理论方面的研究很少,这只是我这些天(重新)入门网络流的一个小总结,问题是大大的有的,欢迎评论!

容量,流量,可行流,残量网络等等基础概念不赘述了

第一类,增广路算法(Augmenting-Path):
    该类算法是基于路径/割的,由Ford和Fulkerson两个人提出,实际上代表了一类算法,:
    从零流开始考虑,假如有这么一条路,这条路从源点开始到达汇点,并且这条路上的每一段都满足$Flow<C$,
    则我们一定能找到这条路上的每一段的$C-Flow$的值当中的最小值$δ$
    把这条路上每一段的$Flow$都加上这个$δ$,一定是一个可行流,这样我们就得到了一个更大的可行流,而这条路就叫做增广路
    我们不断地从起点开始寻找增广路,每次都对其进行增广,直到找不到增广路为止。当找不到增广路的时候,当前的流量就是最大流
    这也是增广路类网络流的核心思路,下来就是这么找增广路,怎么增广了
 
(1)Dfs寻找任意一个增广路,并沿着路进行增广复杂度为$O(E|Maxflow|)$这个算法一般认为这个是Ford-Fulkerson算法
    实际上一般认为的FF算法是不寻找最短增广路也不划分层次图,每次只是对任意一个增广路去增广的算法.
 
(2)Edmonds-Karp/SAP/最短增广路算法 利用BFS寻找最短增广路径,
    由于存图方式的不同,邻接表$O(VE^2)$,邻接矩阵$O(V^3)$
 
(3)MPLA/最短路径增值算法 在残量网络上引入层次,
    构建层次图$O(V)$,$V$个阶段每个阶段多次BFS寻找增广路$O(E^2)$,总复杂度上界为$O(VE^2)$
 
(4)Dinic/Blocking Flow Algorithm/阻塞流算法 用一次DFS代替MPLA的多次BFS增广
    同样建立层次图$O(V)$,$V$个阶段,每个阶段一次DFS寻找增光路$O(VE)$,总复杂度上界为$O(V^2E)$.
 
(5)ISAP,一般认为是加入了GAP优化的SAP算法,时间效率和 Dinic差不多,可以说为 EK算法的优化版。时间复杂度$O(V^2E)$
 
  (6)   Capacity-Scaling/ScalingFord-Fulkerson/Bit-Scaling/容量缩放算法,
    把容量视作二进位数字,从最高位开始,每回合添加一个位数,扩充流量,寻找增广路,填满多出的容量,达到最大流。
    显然,当使用邻接矩阵时,复杂度$O(E^2log(Cmax)V^2)$,使用邻接表时是$O((V+E)Elog(Cmax)) $Cmax$为边上的最大容量
 
第二类,预流推进类算法
   该类算法是以点为基础的
   1.推进/push:
    我们认为汇点是最低点,源点是最高的,推进模拟水流在图上流动到汇点的过程,我们每次先把水流流入中间节点,再逐步向后推进
 
   2.储流,过载/excess/overflowing:
    为了实现推进,我们给每个点一个储流量,点就可以分为储流点/非储流点,储流点(也叫过载点),为了下一步的推进保存当前流量,
    显然,对于任意一个点,实际上的流入==流出,换句话说,除了汇点和源点,所有点应该是不储流的,但显然目前是"过载"/overflowing的
 
   3.可行边/admissible edge与高度标号/height label:
    给每个点进行高度标号,并规定只能从高点向地点流量,与层次图类似
 
   4.预流/preflow:
    由于每次只到下一层推进,所以预先推进源点的流量到所有相邻点中
 
   5.重标号/relabel:
    当一个点无法流动,就抬高它,让水可以回流/流到同高度的点上
 
   6.重回/retreat:
    可以想见的是,所有中间节点都无法继续流下去,显然根据重标号,中间节点会愈来愈高,甚至高于源点,当所有的过载流量终将沿着反向边回流到源点,至此算法结束
 
    实际过程中的基本框架就是对图上各点不断推进和重标号,直到无法进行为止,或者说,最大流存入汇点,多余的流量流回起点,所有其他点均不储流/不过载
    最终汇点的储流量/源点所流出的流量,就是最大流。
    下来就是怎么推进,怎么重标号了
 
  1.朴素预流推进算法/ Push-relabel algorithm with FIFO :
    每个点重标号次数 $O(V)$ 一共 $O(V^2)$ ,邻接矩阵每推一次为 $O(V)$ 邻接表 为常数
    标号一共$O(V^3)$ 或 $O(EV^2)$
    每个边可能被推进$O(V)$饱和情况下一共$O(VE)$非饱和情况下一共$O(EV^2)$
    用一个队列保存储流点即可.
 

  2.重标优先预流推进/Relabel-to-front Algorithm

    建立链表,保存当前图的拓扑序形式,不含源点汇点,按照拓扑序取点,跳过非储流点,把之前被推进过的点重新放入表头,并推进

 
  3.最高标号预流推进/Highest-Label Preflow-Push Algorithm/HLPP
    使用优先队列,每次取出最高标号点进行推进,直到结束,理论复杂度$O(sqrt(m)n^2)$可以使用GAP优化!
 
其实也可以发现,高度标号和层次图有异曲同工之妙
最后 给一个权威表格,甚至引入了动态树,不过没有HLPP算法
Method Complexity Description
Linear programming   Constraints given by the definition of a legal flow. See the linear program here.
Ford–Fulkerson algorithm $O(Emax|f|)$ As long as there is an open path through the residual graph, send the minimum of the residual capacities on the path.

The algorithm is only guaranteed to terminate if all weights are rational. Otherwise it is possible that the algorithm will not converge to the maximum value. However, if the algorithm terminates, it is guaranteed to find the maximum value.

Edmonds–Karp algorithm $O(VE^2)$ A specialization of Ford–Fulkerson, finding augmenting paths with breadth-first search.
Dinic's blocking flow algorithm $O(V^2E)$ In each phase the algorithms builds a layered graph with breadth-first search on the residual graph. The maximum flow in a layered graph can be calculated in O(VE) time, and the maximum number of the phases is n-1. In networks with unit capacities, Dinic's algorithm terminates in O(\min\{V^{2/3}, E^{1/2}\}E) time.
MPM (Malhotra, Pramodh-Kumar and Maheshwari) algorithm
$O(V^3)$ Only works on acyclic networks. Refer to the Original Paper.
Dinic's algorithm $O(VE log(V))$ The dynamic trees data structure speeds up the maximum flow computation in the layered graph to O(V E log(V)).
General push-relabel maximum flow algorithm $O(V^2E)$ The push relabel algorithm maintains a preflow, i.e. a flow function with the possibility of excess in the vertices. The algorithm runs while there is a vertex with positive excess, i.e. an active vertex in the graph. The push operation increases the flow on a residual edge, and a height function on the vertices controls which residual edges can be pushed. The height function is changed with a relabel operation. The proper definitions of these operations guarantee that the resulting flow function is a maximum flow.
Push-relabel algorithm with FIFO vertex selection rule $O(V^3)$ Push-relabel algorithm variant which always selects the most recently active vertex, and performs push operations until the excess is positive or there are admissible residual edges from this vertex.
Push-relabel algorithm with dynamic trees O\left(VE\log {\frac {V^{2}}{E}}\right) The algorithm builds limited size trees on the residual graph regarding to height function. These trees provide multilevel push operations.
KRT (King, Rao, Tarjan)'s algorithm
O(EV\log _{\frac {E}{V\log V}}V)  
Binary blocking flow algorithm
O\left(E\cdot \min(V^{\frac {2}{3}},{\sqrt {E}})\cdot \log {\frac {V^{2}}{E}}\log {U}\right) The value U corresponds to the maximum capacity of the network.
James B Orlin's + KRT (King, Rao, Tarjan)'s algorithm
O(VE) Orlin's algorithm solves max-flow in O(VE) time for E\leq O(V^{{16 \over 15}-\epsilon }) while KRT solves it in O(VE) for E>V^{1+\epsilon }.

感想....

但实际上目前竞赛中常用的算法,无论是Dinic还是ISAP或是HLPP,他们的速度都无法与单纯的最短路算法相比,就连理论上界达到$O(VE)$最高的SPFA都无法达到

而目前科学界理论下界最低的,是Orlin's提出的集大成者,复杂度上界达到$O(VE)$,但是目前还没有进入算法竞赛中来,目前所有的网络流题目复杂度都是按照 O(V2E)来的

但是,实际上无论是网络流还是费用流,我们目前均不需要复杂度如此低的算法

绝大多数模型都不会需要建立一个极端的稠密图/链形图,点数和边数经常是处于一个数量级的,对于$O(EV^2)$的算法足够用了

研究大量复杂度相近而实现方式不同的算法,在OI中是有意义的,

OI赛制中需要大量的不同数据来区分不同的人实力,达到区分度,这也是OI选手对于复杂度,读入输出,花式优化的精益求精的原因,

以Bellmon-Ford最短路为例,的复杂度达到了$O(VE)$

但是实际上有队列优化,不重复入队/重复入队,SLF,均值,转DFS,邻接表指针化等等不同的优化/实现方式

在不同的图中都有不同的效果,即使其理论复杂度依然是$O(VE)$,但只要选手根据不同的图去选择优化方式,就几乎无法被卡了

而且对于一个题,即使你的复杂度无法满足数据量,你依然可以通过其中很多的数据组,得到很多分,此时,一个优化到极致的算法就很重要了...

而在ICPC赛制中,区分度更多的在题目本身的思维,程序准确性,与复杂度上界,因为所有算法都通过所有的样例,也就是说必须用正确的复杂度通过,

在这种情况下,错误的复杂度毫无意义,必须选择一个复杂度稳定,编码容易,灵活的稳定算法,且从下手的一开始,就必须尝试去满足所有的极限数据和情形

OI的90分可以接受,而ICPC90分就是0分,且0ms的AC和10000ms的AC都同样正确,尤其对于网络流,建一个正确合适网络图,比花式优化的效果更大,尤其是减少多余边

总结,最大流的推荐算法有三个,且代码量均不长,资料也可以找到,:
1.Dinic 最常见的算法,可以加上各种优化方法,但无法改变理论上界
2.ISAP 依然是常见的算法,依然可以加上各种优化方法,据说是实践中最快的
3.HLPP 常见(?)算法中理论上界最低的一个,而且也可以加入不少优化,但可以参考的代码较少,尽管这个算法是最短的?
 
参考阅读:
 
赶紧实战去了...
本人现在网络流AC的数量还很少,之后有机会发一下Dinic,HLPP和ISAP的实战情况
再也不进考据,比较的坑了,到时候学动态树/平衡树如果再考据我就吃**
费用流?GAP优化?等我实践完了在加上吧....未完待续
 
有趣的附录:
优化后的SPFA在Codeforce20C这个据说"卡SPFA"的最短路裸题中的速度
 

甚至超过了在VJ的leaderboard中,所有公开代码里最快的dijkstra(Rank5),和第一名相当,但在ICPC中没什么用....

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。

暂无文章

如何将div放置在其容器的底部? - How can I position my div at the bottom of its container?

问题: Given the following HTML: 鉴于以下HTML: <div id="container"> <!-- Other elements here --> <div id="copyright"> Copyright Foo web designs </div> </div> I would like #cop......

富含淀粉
今天
10
0
unity列表控件Horizontal/Vertical/Grid Layout Group用法介绍

1. Grid Layout Group 为Panel控件添加Grid Layout Group,子控件为四个按钮,分别为Grid,Calendar,Gear,User: 默认属性为 为方便演示,按钮的底色为控件自带image,按钮上面的图标为其子...

路过暴风
今天
19
0
Distinct()与lambda? - Distinct() with lambda?

问题: Right, so I have an enumerable and wish to get distinct values from it. 是的,所以我有一个可枚举的,并希望从中获得不同的值。 Using System.Linq , there's of course an ext......

法国红酒甜
今天
16
0
学习编写编译器[关闭] - Learning to write a compiler [closed]

问题: Preferred languages : C/C++, Java, and Ruby. 首选语言 :C / C ++,Java和Ruby。 I am looking for some helpful books/tutorials on how to write your own compiler simply for......

技术盛宴
今天
17
0
OSChina 周一乱弹 —— 毛巾又怎么样?!我在乎的是大姐姐温柔的怀抱!

Osc乱弹歌单(2020)请戳(这里) 【今日歌曲】 @薛定谔的兄弟 :分享洛神有语创建的歌单「我喜欢的音乐」: 《雨 因你而下,于你而止》- Seto 手机党少年们想听歌,请使劲儿戳(这里) @Dan...

小小编辑
今天
48
2

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部