isap算法网络最大流
2017-07-27 20:35
302 查看
ISAP的思路:
当我们使用Dinic跑最大流的时候,我们多次进行了BFS分层,直到汇点不在残余网络之中。而ISAP则只BFS分层一次(事实上你都甚至可以不进行分层,也就比分层慢一点)。ISAP通过新的方式分层。
对于任意一个节点x,当跑完数次最大流之后,我们发现所有与它相连的节点都不满足level[i]+1 == level[x]了。出现这种情况,Dinic的做法是重新分层,而ISAP的做法是将level[x]置成min(level[i])+1,从而构造出一条可行流。
当然,这是有边界的。我们从汇点开始分层,源点的层数最高是n-1(一条链),所以当level[st] >= n的时候,算法结束,残余网络中一定不存在可行流了。
这种方式也就解释了为什么可以不预先分层。因为这样,分层的工作就留给了每一次推进可行流之中(否则无法找到可行流)。
注:分层时从汇点分层。
但是如果仅仅是这样,实际上快不了多少。
真正的优化在于这两个:gap优化和当前弧(cur)优化。
gap优化:
Dinic的反复分层被改成了ISAP的向上构造,而可行流必须满足level[起点] = level[终点]+1,也就是说如果出现了断层,也就是说在某一level的层级中不存在节点,那么就不会再出现可行流(比如这一层是x,那么流无法从lev.(x-1)流到lev.(x+1)),直接结束算法,比不加它的ISAP**快到不知哪里去了**。
cur优化(当前弧):
对于任意一个节点x,假设最大流已经经过它流向下一个节点,而后在某次又流到了它(比如说已经找到一条可行流,从源点重新寻找可行流,再次到达该节点),那么该可行流一定不能再流到之前流过的那些弧了(那些弧已经流过了,再进去相当于又走了一遍老路,但是上一次已经最大化的利用了它的流量限制,也就是说这次是没有任何意义的行为。)
为了避免这种情况,我们用一个数组cur[]来记录每个节点当前流到的弧的编号(这是边表存储的情况。如果是邻接矩阵存储,那就记录当前流到了下一个节点的编号),当下一次又经过该节点的时候,我们只需要再去尝试没有流过的弧了。
举个例子:
节点5有三条弧,分别是arc1,arc2,arc3 。在之前寻找可行流的过程中,经过了arc1。那么将cur[5] = arc2,下一次便从arc2开始寻找可行流。
可能会有这样一个问题:
凭什么就说arc1就没有再走的价值了,那如果上一次通过arc1流向了节点6,而可行流最终是通过节点6的某一条弧流向汇点的,但是节点6不一定只有一条弧啊,下一次还可以走节点6的其他弧。
解释也很简单,这是递归的过程,如果流已经流回到了节点5,那么说明节点6以及arc1所抵达的所有节点都已经进行了这项操作。
当然,如果出现对某结点重新分层的时候,要将该节点的cur置回0(因为当前已经到尾了)。
原文地址
当我们使用Dinic跑最大流的时候,我们多次进行了BFS分层,直到汇点不在残余网络之中。而ISAP则只BFS分层一次(事实上你都甚至可以不进行分层,也就比分层慢一点)。ISAP通过新的方式分层。
对于任意一个节点x,当跑完数次最大流之后,我们发现所有与它相连的节点都不满足level[i]+1 == level[x]了。出现这种情况,Dinic的做法是重新分层,而ISAP的做法是将level[x]置成min(level[i])+1,从而构造出一条可行流。
当然,这是有边界的。我们从汇点开始分层,源点的层数最高是n-1(一条链),所以当level[st] >= n的时候,算法结束,残余网络中一定不存在可行流了。
这种方式也就解释了为什么可以不预先分层。因为这样,分层的工作就留给了每一次推进可行流之中(否则无法找到可行流)。
注:分层时从汇点分层。
但是如果仅仅是这样,实际上快不了多少。
真正的优化在于这两个:gap优化和当前弧(cur)优化。
gap优化:
Dinic的反复分层被改成了ISAP的向上构造,而可行流必须满足level[起点] = level[终点]+1,也就是说如果出现了断层,也就是说在某一level的层级中不存在节点,那么就不会再出现可行流(比如这一层是x,那么流无法从lev.(x-1)流到lev.(x+1)),直接结束算法,比不加它的ISAP**快到不知哪里去了**。
cur优化(当前弧):
对于任意一个节点x,假设最大流已经经过它流向下一个节点,而后在某次又流到了它(比如说已经找到一条可行流,从源点重新寻找可行流,再次到达该节点),那么该可行流一定不能再流到之前流过的那些弧了(那些弧已经流过了,再进去相当于又走了一遍老路,但是上一次已经最大化的利用了它的流量限制,也就是说这次是没有任何意义的行为。)
为了避免这种情况,我们用一个数组cur[]来记录每个节点当前流到的弧的编号(这是边表存储的情况。如果是邻接矩阵存储,那就记录当前流到了下一个节点的编号),当下一次又经过该节点的时候,我们只需要再去尝试没有流过的弧了。
举个例子:
节点5有三条弧,分别是arc1,arc2,arc3 。在之前寻找可行流的过程中,经过了arc1。那么将cur[5] = arc2,下一次便从arc2开始寻找可行流。
可能会有这样一个问题:
凭什么就说arc1就没有再走的价值了,那如果上一次通过arc1流向了节点6,而可行流最终是通过节点6的某一条弧流向汇点的,但是节点6不一定只有一条弧啊,下一次还可以走节点6的其他弧。
解释也很简单,这是递归的过程,如果流已经流回到了节点5,那么说明节点6以及arc1所抵达的所有节点都已经进行了这项操作。
当然,如果出现对某结点重新分层的时候,要将该节点的cur置回0(因为当前已经到尾了)。
原文地址
相关文章推荐
- 最大流Dinic算法讲解 && ISAP 算法解释
- 算法模板——sap网络最大流 1(非递归+邻接矩阵)
- HDU 3549 Flow Problem 网络最大流问题 EK、Dinic、ISAP三种算法
- 算法艺术——网络最大流
- POJ 1273-Drainage Ditches(网络流_最大流_ISAP()算法和EK()算法)
- 算法艺术——网络最大流
- 算法模板——sap网络最大流 2(非递归+邻接表)
- 没日一算法 (网络最大流)3.12
- 算法模板——Dinic网络最大流 2
- 【模板】ISAP网络最大流 (模板题:洛谷P3376)
- 网络最大流的三种基础算法
- isap算法模板poj 1273gap+弧优化 最大流
- 算法艺术——网络最大流 (转自:Rachel-Zhang)
- 面试算法:用队列计算滑动窗口内的最大网络流量
- 算法模板——sap网络最大流 3(递归+邻接矩阵)
- Ural1109_Conference(二分图最大匹配/匈牙利算法/网络最大流)
- isap算法模板poj 1273gap+弧优化 最大流
- 网络流最大流算法(ISAP算法及DINIC算法)
- 算法模板——sap网络最大流 3(递归+邻接表)
- 网络最大流的三种基础算法