算法设计与分析之最大流问题

最近在复习算法 对最大流问题加以学习和总结 配套视频学习效果更加 

算法设计与分析_北京航空航天大学_中国大学MOOC(慕课) (icourse163.org)

一.实际背景/应用场景

最大流算法作为算法设计与分析中比较经典的算法 在实际生活和工程中有着广泛的运用

例如

d2b53efeaf03be48cf6100ee9a81059a.png

对于西气东输问题 我们将问题抽象建模为 图的模型每个中转点相当于一个节点 我们需要考虑的问题是给每一条边输送多少流量 才能保证输送的流量最多 并充分利用管道的容量(根本目的)

流量 :实际每一条边有多少通量

容量 : 实际能够存储多少流量 也是流量的上界

8e5d60be31c522f965be9361e5399e41.png

流量的两个性质

first 容量限制 就是刚才提到的流量不能超过容量

second :流量守恒 :就是说除了源点和汇点 其他所有的节点 流入多少他就会流出多少 不会有剩余

032d97ffd3271a8ba446853ded395bf7.png

有了上述概念 我们就可以定义最大流问题了

给定一个有向图G 以及G中每条边的容量(最大流量) 我们想要求出最大的流量

也就是s中流出的量 或者是 t汇入的流量

但也要满足两个约束条件

1.每条边不能超过容量限制

2.除源点和汇点之外 其他的点流入等于流出 能量守恒

二.求解问题 算法思想

我们定义了问题 并分析了问题的特点 那么我们应该怎样用合适的方法来解决问题呢?

直观策略

8f5ac3c3db973b7345c5e763daa30aa6.png

  1. 首先初始化 让每一条边流量为0 每条边光有容量没有流量 那么总流量就是0

7e4fbee1f1931008330ee0ce57b41946.png

  1. 找出一条从s到p的路径 第一次选路径的时候 路径随便选 只要满足是联通的就行

并取整个路径中最小的容量作为增加的容量一点点进行增流

比如说这个路径s->v2->v3->t 流量 = min{c(i)} = 11

ed96ebf1240a33d846e082d6be774459.png

上图为增流的直观认识

5c6673f6e8a0a979cb17af98d2d0838c.png

3.1重复步骤2 不断进行寻找直到 无法增加路径流量

比如说这个路径s->v1->v3->v4->t 流量 = min{c(j)} = 5

ea3fd371f8662cde0458db074857468d.png

3.2 重复步骤2 不断进行寻找直到 无法增加路径流量

比如说这个路径s->v2->v1->v3->t 流量 = min{14-11=3(注意是剩余流量),5,10-5 = 5} = 3

79cc20e3adb094149c91d83d055819c1.png

那么总流量就由刚才的16增加到了19

e5164b49b5862ceed5e7ac54aec8aadc.png

改进优化解

但这是这是最优方案吗?显然这不是最优

78ecf73da746836354545403df133737.png

a029d126e76cade2ecfb754104d01e5f.png

我们可以看到 图的总流量就是由s边流出的流量之和 这个图里显示就是f = f(s v1) + f(s v2)

尝试增加

我们通过两个图的对比不难发现对于边s v1他的容量没有被充分利用 那么我们是否可以试探性的增加一点点的流量 看他是否仍然满足约束条件?

be1cc955116300a2a26bb30df07afcbc.png

58473015d58a83b64e23e5664742216a.png

上图是我们的尝试过程 显然是不可以的

改变一点点的策略

尝试缩减

681cbf5b3e8b1bbb35817d4886286878.png

光采取增加的方式显然是不行的 那么我们也可以适当减少某个流量值 来平衡能量的重新分配所带来的变化 比如这个 我sv1 +1 会导致 v1 v3也增加了1 既然顶点v3不能流出 他的流入量 还增加了1 那么我们不妨减少他的另外一个渠道的流入量也就是减少v2 v3的流量 再由v2的能量守恒 v2 v4的流量同时也需要增加1 v4的守恒可知 增加v4 t的流量 那么我们的总流量就变成了20

和直观策略 不一样的地方是 多增加了缩减的方法

缩减和逆向是等价的 所以我们引入反向边的技术

利用逆向搜索技术改进优化解

c9ef715995751896f9eaad1eef1011c8.png

大白话:就是引入反向边 来动态判断收缩情况

残存网络

为了快速找到反向边我们引入一种工具 ------ 残存网络

6525b1b2605f858a8541d4f380f1d2f8.png

对于这道题的残存网络 正向边代表剩余的容量 例如sv1的剩余容量是7 所以对应残存网络的正向边也是7 sv1的流量是5那么他的逆向边就是5 正向边代表可支配 反向边代表可余付。

增广路径

ba6de03e8f489f518c1027944fe3445d.png

增广路径是在残存网络上s到t的一条简单路径(没有环) 它帮助我们快速发现可调整的路径 增广路径的寻找可以是任意的 因为之后会进行调整

残存容量

8e4ad753e83689c91787bc0c6ee3368e.png

大白话:增广路径上中流量最小的边的权值 如右图 7-2-11-6-6所以是2

官方话 增广路径中残存容量的最小值

三.从直观策略到Ford-Fulkerson算法

既然我们有了上述的技术 我们便可以从直观逐步过渡到Ford-Fulkerson算法

针对传统的直观增加策略 他只能扩充边的流量 但是不能缩减边的容量

Ford-Fulkerson步骤

e0f2e8751d088d7b97493ab0ade742b7.png

图片介绍了Ford-Fulkerson算法的基本步骤

过渡思路

dd23a0d1763017fd637ab16c1b3b0a03.png

算法实例

d7d3ce1d7d408f839549d64b8e83bd28.png

  1. 初始化流网络G 并构造 对应的Gf

cf85bc612d56d1f8fe36924d730252ab.png

  1. 找到一条增广路径 并更新总流量 总流量 = 增广路径上权值最小的边的权值 = 该增广路径上权值最小的边 注意 增广路径的选取是任意的 只需要满足有向边路径的联通性即可 这个实例选取的是11

56020b020b941b0cc8c1d76a0af0e44c.png

3.找到增广路径之后 更新残存网络 (为了简化起见 需要时可以省略反向边 保持图的简洁性)

91723bb0176664dbd8f333a5f946ec28.png

6897ca6aa6629b18144de0ba7552e918.png

e156b0bb72a184e70059b588fe9cc449.png

4.不断更新 不断发现新的增广路径

4c40c2cff825b3cb474459bc2ad55871.png

  1. 直到无法找到新的增广路径 程序结束。

算法分析(时间复杂度)

1cb0ce765e97de0109c42440f42abb3f.jpeg

55e5a551ddc96b9b56f408eacac11976.png

复杂度也取决于每次增广变化的幅度

9a1d2f1eacce60872d81964b57ffd468.png

29d30bfb8ae1c7ca23114a1ad19f80fe.png

极差的情况是|f*|的情况

算法正确性证明

ccb0937ee562222a6374ec1dcadd8f5a.png

充分性 很简单 反证法 假设存在一条增广路径 则他的流会更长

41f0e3b9288a9f980aa7102412b93be4.png

必要性 怎么建立起这两种桥梁 引入概念割

07598aa3554c80771f7c7dd5ff33a795.png

什么是割 :去掉之后图就不会连通

59e94436dbcbd0f65568147d0d7422a0.png

定义 割的容量

71d7cac1a3bc7d396472ba53fe095bbc.png

流值 = 流出 - 流入

4d932c1a48572b0284086aed6ef9bddf.png

流值定理的证明 能量守恒定律 除了s所有顶点入流量和出流量都是相等的

四 最大流和最小割 && 证明的继续讨论

abeb0759ffeb3ee4a2025fd15df5fcbe.png

回到开头的问题 根据实际意义 定义两个新的定义 最大流和最小割

总会有一种划分 总有一种划分 无论怎么走 都需要经过这一条路径断了他就会卡脖子 不论流量多大都超不过他

最大流的流量会小于最小割容量 卡脖子项目

了解了这些 我们继续看正确性的证明

83364c4a4348d1d1dca1887a6d836b38.png

4ce18ade2a74bc04c88498523efb9a7e.png

课件上写的很清晰 我不做过多解释了

444cbb182f10544633fb17e00cd6e205.png

c585b4cce44f82901fd3796e1e319418.png

之后 当我们碰到多源的问题 我们也可以转换成单源的问题 运用等价替换的思想

aba5e9bde9040e35eb37e0d2102b4665.png

五.实际操作时的易错点:

1.错误点

在实际操作中,以为残存网络不用画反向边而导致计算错误.

反向边在逻辑上对结果也有作用

2.看点例题

d4a0dc8e70d74a82b07bfd0131d82904.png

显然是233    然后他的最小割是s1 求最小割的一个比较简单的方法是看最后一次的残存网络和源点 连边就构成了最小割 割里面的点到外面具有最小的流量。

9641cf9af03b4de2ae46cbdaae61777a.png

在创作中有些仓促,难免有些错误,希望读者批评指正,也期待同大家一起进步~

d85480a1ce099f546252c4e76ff9f817.png

  • 50
    点赞
  • 120
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值