最短路径最大流的SAP算法

本文介绍了最短路径最大流的SAP算法,对比EK算法,SAP算法通过引入距离标号来快速计算增广路径,提高了最大流问题的解决效率。文章详细解释了SAP算法的流程,包括初始化距离标号、寻找增广路径、更新残量网络等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

EK算法的时间复杂度为O(VE^2),效率比较低。使用最短路径最大流的SAP算法,时间复杂度为O(EV^2),速度快很多。

EK算法使用BFS计算增广路径,耗费时间长。SAP算法在求增广路径时,引入了距离标号,加快了计算求增广路径的过程。

下面介绍一些概念:
距离标号:每个结点到宿结点所需要经过的弧数量的下界。
允许弧:d[u] = d[v] + 1,并且c[u, v]>0的边称为允许弧。每次都走允许弧可以保证走的路径时最短路径。

那么SAP的算法框架可以归纳如下:
1. 用BFS初始化网络中结点的距离标号。
2. 从源点依次往后遍历允许弧到宿点。得到一个增广路。
3. 更新残量网络。重复步骤1~3。
4. 当更新到某个点找不到允许弧时,更新当前结点的d。更新方法d[u] = min(d[vi] + 1)。然后回溯到上一个点重新允许弧。当没有任何可达边时,复制为无效值。
5. 当源点的d值大与网络中结点的数量时,表示网络中再无增广路,结束循环。

编码实现如下:

#-*- coding: utf-8 -*-

topo = { 1 : {2 : 2, 3 : 5},
         2 : {1 : 0, 3 : 2, 4 : 2},
         3 : {1 : 0, 2 : 0, 4 : 3},
         4 : {2 : 0, 3 : 0} }

def init_dis(s, t, dis):
    if s == t: return
    for node in topo[t]:
        if topo[node][t] > 0 and dis[node] == 0:
            dis[node] = dis[t] + 1
            init_dis(s, node, dis)

def get_augment_path(s, t, dis, pre, remain):
    if s == t: return remain
    for node, cap in topo[s].items():
        if cap > 0 and dis[s] == dis[node] + 1 and pre[node] == 0:
            if remain > cap: remain = cap
            pre[node] = s
            rst = get_augment_path(node, t, dis, pre, remain)
            if rst != 999:
                topo[s][node] = topo[s][node] - rst
                topo[node][s] = topo[node][s] + rst
                return rst
            else: # 回溯
                rst = get_augment_path(node, t, dis, pre, remain)
                if rst != 999:
                    topo[s][node] = topo[s][node] - rst
                    topo[node][s] = topo[node][s] + rst
                    return rst
    else: # 没有允许弧,更新d
        min_d = 999
        for node in topo[s]:
            if dis[node] + 1 < min_d and topo[s][node] > 0: min_d = dis[node] + 1
        dis[s] = min_d

    return 999

def sap(s, t):
    dis = [0 for i in range(len(topo) + 1)]
    init_dis(1, 4, dis)
    flow = 0

    while dis[s] < len(topo):
        pre = [0 for i in range(len(topo) + 1)]
        rst = get_augment_path(1, 4, dis, pre, 999)
        if rst != 999: flow = flow + rst

    print flow

if __name__ == '__main__':
    sap(1, 4)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值