码迷,mamicode.com
首页 > 编程语言 > 详细

ISAP 算法

时间:2020-02-11 19:15:17      阅读:99      评论:0      收藏:0      [点我收藏+]

标签:ret   next   argument   aci   line   pre   for   深度   strong   

\(\quad\) Dinic 算法其实已经足够处理大多数的网络流了,但还不够快。接下来介绍的是最优秀的增广路最大流算法:ISAP(Improve Shortest Argumenting Path)。它的时间复杂度上界与 Dinic 一样,为 \(O(n ^ 2 \cdot m)\)
\(\quad\) 先分析 Dinic 的优化空间。Dinic 必须在每一次 dfs 前通过 bfs 获取一次所有点的深度(Depth),这样做效率是极其低下的。ISAP 通过一种神奇的方法解决了这个问题。
\(\quad\) ISAP 对深度有不同的定义。对于一个点 \(i\),它的深度 \(dep_i\) 为源点 \(s\) 到汇点 \(t\) 的最短距离与它到源点 \(s\) 的最短距离的差。另外,定义 \(gap_i\) 为所有满足 \(dep_j = i\) 的点 \(j\) 的数量,即所有深度为 \(i\) 的点数。显然,当 \(\exists i\) 使得 \(gap_i = 0\) 时,即分层图出现断层时,残余网络中不存在一条自 \(s\)\(t\) 的增广路。


int dfs(int node, int flow){
    if(node == t || !flow)
        return flow;
    int stream = 0, f;
    for(int i = head[node]; i != -1; i = edge[i].next)
        if(dep[edge[i].to] == dep[node] - 1 && (f = dfs(edge[i].to, min(flow, edge[i].capacity)))){
            flow -= f, stream += f;
            edge[i].capacity -= f, edge[i ^ 1].capacity += f;
            if(!flow)
                return stream;
        }
    ...... 
    return stream;
}

\(\quad\) 上面是 ISAP 的 dfs 代码片段。可以发现,除了隐藏的省略号部分,它和 Dinic 的是几乎一样的。而隐藏部分是为了更新 \(dep\)\(gap\),省去多次的 bfs。
\(\quad\) 执行“......”的先决条件是 \(flow \neq 0\)。此时说明该点 \(node\) 已经没有出边能够接受流量了,那么只需要

if(--gap[dep[node]++])
    ++gap[dep[node]];
else
    gap[s] = n + 1;

即可更新 \(dep\)\(gap\)
\(\quad\) 这样的算法不但优秀,也很好写,可以作为网络流的主要算法。

ISAP 算法

标签:ret   next   argument   aci   line   pre   for   深度   strong   

原文地址:https://www.cnblogs.com/natsuka/p/12296222.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!