求解网络流最大流问题有很多算法,ISAP 是图论求最大流的算法之一,它很好的平衡了运行时间和程序复杂度之间的关系,因此性价比很高。
而 HLPP 算法理论复杂度十分优秀,在实际运用中由于上界更紧而并不一定会快于 ISAP,但是 HLPP 在分层图中表现十分出色,甚至比在分层图上复杂度为 $O(n^2)$ 的 MPM 算法还快。
这里简单的给出这两个算法的思想以及代码实现。
ISAP
概括地说,ISAP (Improved Shortest Augmenting Path) 算法就是不停地找最短增广路,找到之后增广;如果遇到死路就 retreat,直到发现 $s$, $t$ 不连通,算法结束。找最短路本质上就是无权最短路径问题,因此采用 BFS 的思想。具体来说,使用一个数组 $d$,记录每个节点到汇点 $t$ 的最短距离。搜索的时候,只沿着满足 $d[u] = d[v] + 1$ 的边 $u \rightarrow v$(这样的边称为允许弧)走。显然,这样走出来的一定是最短路。
实现
ISAP 有许多实现,这里采用没有预先 BFS 标号的递归实现 (对于网格图和分层图一定要写 BFS 标号),同时开启了当前弧和 gap 优化,时间复杂度 $O(n^2m)$
代码
1 | const int MAXN = 1000010; |
效率
默认使用读入优化,以下数据均算上了输入输出时间。
在一般情况下,这份代码在 $2000$ 个点 $4000000$ 条边上耗时 $450 ms$ 左右,在 $1000000$ 个点 $2000000$ 条边上耗时 $400 ms$ 左右,注意如果图很小,建议将 vector
换成前向星,反之建议使用 vector
。
HLPP
HLPP (Highest Label Preflow Push) 算法,这个算法全称叫最高标号预流推进,这里默认已经学会了一般预流推进算法。
效率较高的预流推进一般只有前置重贴标签算法 (Relabel-to-front Algorithm) 和最高标号预流推进算法 (Highest Label Preflow Push Algorithm)。
前置重贴标签算法
- 建立一个
list
,里面包含所有点(但不包括源点汇点)。
注:此list从头到尾一直都是当下 admissible network 的拓扑排序。 - preflow。
- 按照
list
顺序读取各点- 如果不是含水点,就继续下一个点,
- 如果是含水点,就discharge,并且于discharge完之后
- 如果刚才的discharge有抬高此点(有relabel),
就把此点移到list开头,并重新由list开头读取。 - 如果刚才的discharge没有抬高此点(没有relabel),
就继续下一个点。
- 如果刚才的discharge有抬高此点(有relabel),
时间复杂度 $O(n^3)$
最高标号预流推进算法
类似于前置重贴标签算法,最高标号预流推进算法只是每次找最高的含水点进行 discharge(不包括源点汇点),直到图上无含水点(不包括源点汇点),同时 HLPP 必须要加上 gap 优化,否则其复杂度无法降低至 $O(n^2 \sqrt m)$
代码
1 | /* |
效率
同上面的 ISAP,HLPP 分别耗时 $650 ms$ 和 $600 ms$ 左右。
总结
一般情况使用性价比较高的 ISAP,当遇到分层图问题时尽量使用 HLPP,如 ZOJ-2364/SGU-212 Data Transmission,此题求一个分层图的阻塞流,HLPP 能够很快的得出答案,而 ISAP / Dinic 必须要使用贪心预流的技术才能通过。