【网络流】网络流学习笔记Part2ISAP算法

来源:互联网 发布:redis 数据库 编辑:程序博客网 时间:2024/05/18 01:52

说实话ISAP的文献真的不太好找= =而且介绍的没有太详细,不像SAP Dinic比较普及。

ISAP其实是改进的SAP算法,要学ISAP就先去看一下SAP好了。(事实上很多人会把ISAP和SAP搞混了。尤其在国内,很多人会直接管ISAP叫SAP)

SAP算法(即Edmonds-Karp算法):

不断进行BFS找增广路径,那么最多找V*E次就一定不存在增广路径了。

时间复杂度 O(V*E^2)

ISAP算法:

通过维护距离标号使得寻找增广路径的过程被简化从而提高效率。距离标号可以使某个点到汇点sink的最少的弧的数量,也可以是源点到该点的最少的弧的数量。通常我们使用前者,这样初始化时就可以通过一次反向的BFS来记录距离标号。

假设点i的距离标号dis[i]=dis[j]+1,则称弧(i,j)为允许弧,在增广时我们只需要找允许弧,就可以使所走路径一定是最短路。

算法的执行:

首先反向BFS初始化距离标号

从源点开始进行增广

设当前访问点为点i

1>若当前i点存在出弧且出弧为允许弧,沿出弧向下执行

2>若当前i点不存在出弧即i为当前路径终点,直接进行增广

3>若当前i点存在出弧但是出弧中不存在允许弧,更新i点的距离标号为所有出弧指向的点的距离标号的最小值+1,之后返回上层。当dis[source]≥顶点数n时,算法全过程停止。

由于蒟蒻太弱了不太会写伪代码,这里引用一下@柔软的小猫点击打开链接的伪代码

algorithm Improved-Shortest-Augmenting-Path1 f <-- 02 从终点 t 开始进行一遍反向 BFS 求得所有顶点的起始距离标号 d(i)3 i <-- s4 while d(s) < n do5 if i = t then // 找到增广路6 Augment7 i <-- s // 从源点 s 开始下次寻找8 if Gf 包含从 i 出发的一条允许弧 (i,j)9 then Advance(i)10 else Retreat(i) // 没有从 i 出发的允许弧则回退11 return fprocedure Advance(i)1 设 (i,j) 为从 i 出发的一条允许弧2 pi(j) <-- i // 保存一条反向路径,为回退时准备3 i <-- j // 前进一步,使 j 成为当前结点procedure Retreat(i)1 d(i) <-- 1 + min{d(j):(i,j)属于残量网络Gf} // 称为重标号的操作2 if i != s3 then i <-- pi(i) // 回退一步procedure Augment1 pi 中记录为当前找到的增广路 P2 delta <-- min{rij:(i,j)属于P}3 沿路径 P 增广 delta 的流量4 更新残量网络 Gf

邻接表优化

如果顶点多的话,往往N^2存不下,这时候就要存边:
存每条边的出发点,终止点和价值,然后排序一下,再记录每个出发点的位置。以后要调用从出发点出发的边时候,只需要从记录的位置开始找即可(其实可以用链表)。优点是时间加快空间节省,缺点是编程复杂度将变大,所以在题目允许的情况下,建议使用邻接矩阵。

GAP优化

如果一次重标号时,出现距离断层,则可以证明ST无可行流,此时则可以直接退出算法。

当前弧优化

为了使每次找增广路的时间变成均摊O(V),还有一个重要的优化是对于每个点保存“当前弧”:初始时当前弧是邻接表的第一条弧;在邻接表中查找时从当前弧开始查找,找到了一条允许弧,就把这条弧设为当前弧;改变距离标号时,把当前弧重新设为邻接表的第一条弧。




1 0
原创粉丝点击