网络流探索:解决网络最大流问题的算法集锦

1.初识网络流

网络流一直是初学者心中很难过去的一道坎,很多人说它是一个不像DFS/BFS那么直观的算法,同时网上也有各种参差不齐的材料,让人感到一知半解。
如果你也有这样的感觉,那么不要灰心,坚持住,因为网络流是组合优化理论的明珠,是你走向计算机理论深邃奥秘的第一步。
路径这个概念虽然非常基础,但是有着很多的应用,例如,可以把交通网络看成一个图,那么图上的路径就是一个合法的交通路线,我们可以通过最短路径算法求出最佳的路径。同样我们可以把社会网络,也就是人和人的关系看成一个网络,我们可以用路径来分析社会网络的各种性质关系;甚至我们可以把编写的程序看成一个图,可以通过路径建模程序当中的性质,例如,可以证明程序当中犯的某一些错误是否会发生,这些都是在图论的基础上建立的各种各样有趣的应用。

2.最大流问题的定义与基础

最大流问题属于图论的范畴,这里的图是有向有权图,边都有方向和权重,图中有很多节点,其中一个节点是起点,记作s,还有一个节点是终点,记作t。
可以这样理解最大流问题:我们希望把水从节点s送到终点t,水要通过管道来输送,这些管道就是图中的边,边都有权重,权重可以理解为管道的容量,否则可能会导致压力过大导致管道爆裂,那么,给定管道的限制,那么最大流是多少?
第一步创建residual graph,它的权重等于水管的空闲量,初始时没有水流,所以空闲量等于容量;
在这里插入图片描述
最直观的简单算法为:
第二步是在residual graph找到augumenting path,augumenting path是指从起点s到终点t的简单路径,寻找路径上最小的权重,假设最小权重为x,那么该路径下最多只能传输x单位的水流,再多的话,最弱的水管会爆裂。此外,我们让x单位的水流过这条路径,那么这条路径下所有边的空闲量都要减去x,不断重复第二步的过程,直到找不到起点到终点的路径,这就说明没有办法把更多的水从起点送到终点,这时候就应该终止循环!
在这里插入图片描述
**简单算法有时候会失败!**这种算法只能找到blocking flow阻塞流,阻塞流意思是把网络给阻塞了,没办法传输更多的水流,阻塞流未必是最大流。具体示例如下所示:
在这里插入图片描述
这说明简单算法不能保证结果是最大流,后序介绍的算法可以保证求出的结果一定是最大流

3.Ford–Fulkerson algorithm

前面说简单算法不一定找到最大流,究其原因主要是简单算法不会反悔,不能纠正错误,一旦坏的路径被选中,算法就无法找到最大流。
但是Ford–Fulkerson algorithm一定可以找到最大流,因为它可以把不好的路径给撤销掉
Ford–Fulkerson algorithm与简单算法相比,唯一的区别是添加一条反向的路径,这样一来,就算之前选择的路径不好,也可以原路撤销返回。
在这里插入图片描述
Ford-Fulkerson算法是一种用于解决网络最大流问题的经典算法。它基于寻找增广路径的思想,通过不断寻找增广路径来增加流量,直到无法找到增广路径为止。
该算法的步骤如下:

  1. 创建一个residual graph并初始化所有边的流量为0。
  2. 当存在从源节点到汇节点的增广路径时:
    • 使用深度优先搜索或广度优先搜索来寻找一条增广路径。增广路径是指路径上的每条边的剩余容量大于0。
    • 在找到增广路径后,通过更新路径上的边的剩余容量来增加流量。
    • 更新路径上的边的剩余容量,即减少正向边的剩余容量,增加反向边的剩余容量
  3. 当无法找到增广路径时,算法终止。此时,得到的流就是最大流。
    在这里插入图片描述
    需要注意的是,Ford-Fulkerson算法的时间复杂度很慢,并且会在某些情况下陷入无限循环,因此为了保证算法的终止和收敛性,通常需要采用其他技术,如Edmonds-Karp算法中使用的最短增广路径策略。
    总之,Ford-Fulkerson算法是一种通过不断寻找增广路径来逐步增加流量的经典算法,用于解决网络最大流问题。

4.Edmonds-Karp Algorithm

Edmonds-Karp论文发表在1972年,比Ford–Fulkerson algorithm晚了12年,Edmonds-Karp算法不是新的算法,而是Ford–Fulkerson algorithm算法的特例,Edmonds和Karp的贡献在于他们证明了更好的时间复杂度,时间复杂度不依赖于最大流的大小。Edmonds-Karp Algorithm与Edmonds-Karp Algorithm几乎完全一样,唯一的区别在于Edmonds-Karp Algorithm寻找路径的时候要用最短路径算法

Edmonds-Karp算法是Ford-Fulkerson算法的一种改进版本,用于求解网络最大流问题。它通过使用广度优先搜索来选择最短增广路径,从而提高算法的效率和收敛速度。
以下是Edmonds-Karp算法的详细步骤:

  1. 初始化所有边的流量为0。
  2. While 存在从源节点到汇节点的增广路径:
    • 使用广度优先搜索来找到一条最短增广路径。最短增广路径是指路径上的边数最少,即最短距离最短。
    • 在找到最短增广路径后,计算路径上的最小剩余容量。最小剩余容量是指路径上所有边的剩余容量的最小值。
    • 通过更新路径上的边的流量来增加流量,即在正向边上增加流量,或在反向边上减少流量。
    • 更新路径上的边的剩余容量,即减少正向边的剩余容量,增加反向边的剩余容量。
  3. 当不存在从源节点到汇节点的增广路径时,算法终止。此时,得到的流就是最大流。
    Edmonds-Karp算法通过使用广度优先搜索来选择最短增广路径,相比于Ford-Fulkerson算法的深度优先搜索,它能够更快地找到增广路径。这是因为广度优先搜索以层次化的方式逐层遍历网络,从而找到最短距离的路径。这种选择最短增广路径的策略确保了算法的收敛性和终止性。
    总结来说,Edmonds-Karp算法是一种基于广度优先搜索的改进Ford-Fulkerson算法,用于求解网络最大流问题。它通过选择最短增广路径来提高算法的效率和收敛速度。
    在这里插入图片描述
    从图中可以看出,这个时间复杂度比Ford-Fulkerson算法要好的多,因为它不依赖于网络流的大小。Edmonds和Karp两个人更好的贡献是证明了更好的时间复杂度,下面会简单分析一下Edmonds-Karp算法的时间复杂度。
    主要意思就是:假设residual graph有m条边,n个点,算法的每一轮循环都要在residual graph中寻找无权的最短路,所以需要O(m)的时间复杂度,原因是,如果原图中有m条边,那么residual graph中最多有m条反向边,所以residual graph一共有不超过2m条边,如果一个无权图有2m条边,那么寻找最短路就需要O(m)的时间。此外,Edmonds和Karp两个人证明了算法最多循环mn轮,即,算法每一轮需要O(m)的时间,最多循环mn轮,所以最坏时间复杂度是 O ( m 2 n ) O(m^2n) O(m2n),这个时间复杂度与最大流无关,最大流可以是几百几千万,都不会影响时间复杂度的大小。
    在这里插入图片描述

5.Dinic’s Algorithm

Dinic’s Algorithm它是寻找网络最大流的算法,它的时间复杂度比Edmonds-Karp Algorithm更低,先简单比较一下两种算法的时间复杂度,具体如下所示:
在这里插入图片描述
从图中可以看出,若边的数量为m,点的数量为n,则Edmonds-Karp Algorithm的时间复杂度为O( m 2 n m^2n m2n),而Dinic’s Algorithm的时间复杂度为O( m n 2 mn^2 mn2),但是一般边的个数m会远大于点的个数n,因此Dinic’s Algorithm的时间复杂度会更低。
Dinic’s Algorithm要用到Blocking Flow(阻塞流),阻塞流意思是拥有这些流量,就不能增加更多流量,也就是这些流量阻塞了管道。
最大流一定是阻塞流,但是阻塞流未必是最大流。 前面介绍的简单算法一定能找到阻塞流,但是未必能找到最大流。
此外,Dinic’s Algorithm还会用到Level Graph ,下面简单介绍一下Level Graph。
给定右边的原图,下面一步步构造Level Graph,从起点S开始,走一步能达到 v 1 , v 2 v_{1},v_{2} v1,v2这两个节点,把 v 1 , v 2 v_{1},v_{2} v1,v2加入左边的Level Graph,同时把 v 1 , v 2 v_{1},v_{2} v1,v2记作第一层,意思是从起点出发走一步能达到,保留从起点S到第一层的边。再看右边的原图,从第一层的 v 1 , v 2 v_{1},v_{2} v1,v2出发,走一步能达到 v 3 , v 4 v_{3},v_{4} v3,v4两个节点,把 v 3 , v 4 v_{3},v_{4} v3,v4加入左边的Level Graph,同时把 v 3 , v 4 v_{3},v_{4} v3,v4记作第二层,意思是从起点出发走两步能达到,保留从第一层到第二层的三条边。再看右边的原图,从第二层的节点 v 3 , v 4 v_{3},v_{4} v3,v4出发。走一步可以达到终点t,把终点t加入左边的Level Graph,同时把终点t记作第三层,意思是从起点出发走三步能达到,并保留第二层到第三层的边,Level Graph的边指的是从上一层到下一层。,下图右侧两条紫色的边分别是从第一层到第一层,第二层到第二层,因此不能加入Level Graph中。
在这里插入图片描述
掌握了与预备知识,那么下面进入正题!
Dinic’s算法是一种高效的解决最大流问题的算法,它基于增广路径和分层图的概念。以下是Dinic’s算法的步骤总结:

  1. 构建初始残余网络(residual graph):将所有边的流量初始化为0,并根据网络中的边构建初始的残余网络(residual graph)。
  2. 构建分层图(Level Graph):使用广度优先搜索(BFS)构建分层图。分层图是在残余网络中,将每个节点按照其到源节点的最短距离分层的图。
  3. 寻找增广路径:在分层图中,从源节点到汇节点寻找增广路径。增广路径是指路径上所有边的剩余容量大于0。
  4. 更新阻塞流和反向边:如果找到增广路径,则将对应residual graph路径上的最小剩余容量作为阻塞流,增加流量,并更新路径上的边的剩余容量。同时,对于路径上的每条边,增加反向边的剩余容量。
  5. 重复迭代:重复步骤2到步骤4,直到无法再找到增广路径为止。每次迭代中,分层图(Level Graph)会更新,从而更好地指导下一次增广路径的寻找。
  6. 终止条件:当无法再找到增广路径时,算法终止。此时,得到的流就是最大流。
    Dinic’s算法通过构建分层图(Level Graph)来指导增广路径的寻找,从而减少了无效的搜索,提高了算法的效率。在寻找增广路径时,除了更新阻塞流和路径上的边的剩余容量外,还需要增加反向边的剩余容量,以确保反向流的正确性。
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/e82e433f7a91418d891a1c6d62c1f6fe.png

6.Minimum Cut Problem

Minimum Cut Problem翻译为最小割问题,最小割与最大流是等价的。
可以这样理解最小割问题,Cut的意思是割断一些管道,让水不能从起点s流向终点t,Min-Cut最小割的目标是让割断的水管总容量最小,也就是说,我尽量割断细的管道,而不是粗的管道,我用最小的力气就能截断水流。
对于同一张图,有不同的切断方式,左边的割量为3,是最小割,而右边的割为6,它不是最小割!此外,还需要注意,最小割的并不唯一!
在这里插入图片描述

7.Max-Flow Min-Cut Theorem

最大流最小割定理(Max-Flow Min-Cut Theorem)说明了最大流问题和最小割问题的等价性!
对于一个网络流问题,最大流的流量等于最小割的容量,也就是说,你求出了最大流问题,就相当于求出了最小割问题。这个定理是Ford和Fulkerson两个人在1962年提出来的。
在这里插入图片描述
接下来介绍一种寻找最小割问题!
这种方法把最小割问题等价转换为最大流问题,只要我们找到最大流,我们就能找到最小割。
简单来说就是:
1.使用Edmonds-Karp Algorithm找到最终的residual graph;
2.然后在最终的residual graph去掉所有的反向边;
3.在去掉所有反向边的residual graph后,从该图中找到从s出发能到达的所有顶点,让其作为集合的一部分,剩下的作为集合的剩余部分;
4.最后根据划分好的两部分集合找到最小割。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/103849.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

redis 主从复制

1 . redis主从复制 – 配置文件方式实现 1.1简介 : 主机更新后根据配置和策略,自动同步到备机的master/slave机制,Master以写为主,Slave以读为主 1.2 具体作用 读写分离,性能扩展,降低主服务器的压力容灾&#xff0c…

对比Vue2和Vue3的自定义指令

一、自定义指令简介 自定义指令是Vue提供的能力,用于注册自定义的指令,从而实现一些自定义的DOM操作。 二、Vue2中自定义指令 在Vue2中,自定义指令通过全局方法Vue.directive()进行注册: // 注册全局指令v-focus Vue.directive(focus, {inserted: function(el) {el.focus()…

mysql 命令行安装

一、安装包下载 1、下载压缩包 (1)公众号获取 关注微信公众号【I am Walker】,回复“mysql”获取 (2)官网下载 安装地址MySQL :: Download MySQL Community Server ​ ​ 二、解压 下载完之后进行解压&…

【数据结构】线性表(十一)队列:双端队列及其基本操作(初始化、判空、判满、头部入队、尾部入队、头部出队、尾部出队、存取队首队尾元素)

文章目录 一、队列1. 定义2. 基本操作 二、顺序队列三、链式队列双端队列0. 头文件1. 队列结构体2. 初始化3. 判断队列是否为空4. 判断队列是否已满5. 头部入队6. 尾部入队7. 头部出队8. 尾部出队9. 存取队列头部的元素10. 存取队列尾部的元素11. 释放队列内存12. 主函数13. 代…

已更新!宝藏教程!MYSQL-第六章节多表查询(一对一,多对多,一对多),连接查询(内,外连接),联合查询,子查询 代码例题详解这一篇就够了(附数据准备代码)

c知识点合集已经完成欢迎前往主页查看,点点赞点点关注不迷路哦 点我进入c第一章知识点合集 MYSQL第一章节DDL数据定义语言的操作----点我进入 MYSQL第二章节DDL-数据库操作语言 DQL-数据查询语言----点我进入 MYSQL第三章节DCL-管理用户,控制权限----点我…

28、Flink 的SQL之DROP 、ALTER 、INSERT 、ANALYZE 语句

Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…

笔记/日记应用 memos

memos ,一款很惊艳的笔记应用,UI很漂亮,交互体验也很好,还有其他的小伙伴基于memos开发了不同平台的客户端。 图源-Gihub页 可以说这个是私人笔记系统的天花板,推荐给大家。

vue重修之Vuex【上部】

文章目录 版权声明Vuex 概述Vuex 的主要概念和组件 vuex的使用状态 (state)Vuex特点 访问vuex中数据$store访问mapState辅助函数访问 开启严格模式及Vuex的单项数据流突变(mutations)mutations初识带参 mutations辅助函数 mapMuta…

N——>BatchSize 数据维度理解和处理(chun, cat, squeeze, unsqueeze)

数据处理之N——>BatchSize N——>batch_size train_data TensorDataset(torch.Tensor(x_train).double(), torch.Tensor(y_train).double()) train_loader DataLoader(train_data, batch_sizeargs.bs, shuffleTrue, drop_lastTrue) for batch_idx, (inputs, results…

自动化测试07Selenium01

目录 什么是自动化测试 Selenium介绍 Selenium是什么 Selenium特点 工作原理 SeleniumJava环境搭建 Selenium常用的API使用 定位元素findElement CSS选择语法 id选择器:#id 类选择 .class 标签选择器 标签名 后代选择器 父级选择器 自己选择器 xpath …

Django实现音乐网站 (22)

使用Python Django框架做一个音乐网站, 本篇音乐播放器功能完善:顺序播放、设置播放数、歌词滚动等功能。 目录 顺序播放 设置顺序播放 单曲播放数 添加路由 视图处理 模板处理 歌词滚动 视图内容返回修改 样式设置 模板内容 歌词滚动脚本 歌…

【C++代码】安排行程,N皇后,解数独--代码随想录

题目:重新安排行程 给你一份航线列表 tickets ,其中 tickets[i] [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。所有这些机票都属于一个从 JFK(肯尼迪国际机场)出发的先生,所以该行程必…

[Docker]二.Docker 镜像,仓库,容器介绍以及详解

一.Docker 镜像,容器,仓库的简单介绍 通俗来讲:镜像相当于VM虚拟机中的ios文件,容器相当于虚拟机系统,仓库相当于系统中的进程或者执行文件,容器是通过镜像创建的 1.镜像 Docker 镜像就是一个 Linux 的文件系统( Root FileSystem ),这个文…

一百九十五、MySQL——MySQL数据库创建只读权限的账号(附流程截图)

一、目的 在团队开发过程中,为了实现数据共享以及避免其他团队修改库表数据,需要提供数据库只读权限的账号,因此以MySQL数据库为例,创建MySQL数据库只读权限的账号 二、实施步骤 (一)第一步,…

栈(Stack)的概念+MyStack的实现+栈的应用

文章目录 栈(Stack)一、 栈的概念1.栈的方法2.源码分析 二、MyStack的实现1.MyStack的成员变量2.push方法3.isEmpty方法和pop方法4.peek方法 三、栈的应用1.将递归转化为循环1.调用递归打印2.通过栈逆序打印链表 栈(Stack) 一、 栈…

Nginx动静分离

为了加快网站的解析速度,可以把动态页面和静态页面由不同的服务器来解析,加快解析速度。降低原来单个服务器的压力。 在动静分离的tomcat的时候比较明显,因为tomcat解析静态很慢,其实这些原理的话都很好理解,简单来说&…

T113-S3-buildroot文件系统tar解压缩gz文件

目录 前言 一、现象描述 二、解决方案 三、tar解压缩.gz文件 总结 前言 本文主要介绍全志T113-S3平台官方SDK,buildroot文件系统tar不支持.gz文件解压缩的问题以及如何配置buildroot文件系统解决该问题的方法介绍。 一、现象描述 在buildroot文件系统中&#xff…

Doceker-compose——容器群集编排管理工具

目录 Docker-compose 1、Docker-compose 的三大概念 2、YAML文件格式及编写注意事项 1)使用 YAML 时需要注意下面事项 2)ymal文件格式 3)json格式 3、Docker Compose配置常用字段 4、Docker-compose的四种重启策略 5、Docker Compos…

强劲升级,太极2.x你值得拥有!

嗨,大家好,最近桃桃没顾得上给大家分享好用好玩的软件。 还记得前段时间给大家分享的太极1.0软件? 最近大佬对软件进行了全新升级,升级后的功能更强更稳定,轻度用户使用基本功能就已经足够了,壕无人性的同学…

Openssl数据安全传输平台004:Socket C-API封装为C++类 / 服务端及客户端代码框架和实现

文章目录 0. 代码仓库1. 客户端C API2. 客户端C API的封装分析2.1 sckClient_init()和sckClient_destroy()2.2 sckClient_connect2.3 sckClient_closeconn()2.4 sckClient_send()2.5 sckClient_rev()2.6 sck_FreeMem 3. 客户端C API4. 服务端C API5. 服务端C6. 客户端和服务端代…
最新文章