【图与网络数学模型】3.Ford-Fulkerson算法求解网络最大流问题

news2025/2/25 8:19:22

在这里插入图片描述

【图与网络数学模型】3.Ford-Fulkerson算法求解网络最大流问题

  • 一、网络流模型
    • 1. 概述
    • 2. 可行流
    • 3. 增广链
  • 二、示例
    • 1. 最大流问题
    • 2. Alternate Formulation:最小截量问题
  • 三、Ford-Fulkerson 算法
    • 1. 导入库
    • 2. 初始化残差图
    • 3. 定义查找增广路径
    • 4. 定义循环
    • 5. 程序运行
  • 四、其它发现
  • 参考文献


一、网络流模型

1. 概述

许多系统中包含了流量问题,例如,公路系统中有车辆流,控制系统中有信息流,供水系统中有水流,金融系统中有现金流等。

在生物安全领域和医疗系统中,也包括就诊、挂号、检查、治疗、转院等过程涉及的患者流,医疗设备、药品、医用材料等的采购、配送、使用等过程涉及的医疗资源流,以及医疗质量控制流和医保支付流等等。

对于这样一些包含了流量问题的系统,我们往往要求出其系统的最大流量。给一个带收发点的网络,每条弧的赋权称为容量,在不超过每条弧的容量的前提下,确定每条弧的流量,求出从发点到收点的最大流量,这类问题通常称为最大流问题

2. 可行流

  • 网络流一般在有向图上讨论
  • 定义网络上支路的容量为其最大通过能力,记为 c i j c_{ij} cij,支路上的实际流量记为 f i j f_{ij} fij
  • 图中规定一个发点s,一个收点t
  • 节点没有容量限制,流在节点不会存储
  • 容量限制条件:0 ≤ f i j f_{ij} fij c i j c_{ij} cij
  • 平衡条件:
    ∑ v j ∈ A ( v i ) f i j − ∑ v j ∈ B ( v i ) f j i = { v ( f ) i = s 0 i ≠ s , t − v ( f ) i = t \sum_{v_j \in A\left(v_i\right)} f_{i j}-\sum_{v_j \in B\left(v_i\right)} f_{j i}=\left\{\begin{array}{cc} v(f) & i=s \\ 0 & i \neq s, t \\ -v(f) & i=t \end{array}\right. vjA(vi)fijvjB(vi)fji= v(f)0v(f)i=si=s,ti=t

满足上述条件的网络流称为可行流,总存在最大可行流。

当支路上 f i j = c i j f_{ij}=c_{ij} fij=cij ,称为饱和弧;v( f )为可行流的流量。

最大流问题也是一个线性规划问题。

3. 增广链

设 f 是一个可行流, μ \mu μ v s v_s vs v t v_t vt 到的一条链,若 μ \mu μ 满足下列条件,则 μ \mu μ 是可行流的一条增广链

  1. ( v i , v j ) ∈ μ + \left(v_i, v_j\right) \in \mu^{+} (vi,vj)μ+上, 0 ≤ f i j < c i j 0\leq{f}_{i_j}<c_{i j} 0fij<cij,即 μ + \mu^{+} μ+ 中每一条弧是非饱和弧;
  2. ( v i , v j ) ∈ μ − \left(v_i, v_j\right) \in \mu^{-} (vi,vj)μ上, 0 < f i j ≤ c i j 0<f_{i j} \leq c_{i j} 0<fijcij,即 μ − \mu^{-} μ中每一条弧是非零流孤。

二、示例

1. 最大流问题

给定一个图,该图表示每个边都有一个容量的流网络。此外,给定图中的两个顶点源 ‘s’ 和接收器 ‘t’,使用以下约束找到从 s 到 t 的最大可能流量:

在这里插入图片描述

该问题的最大流量为23:

在这里插入图片描述

2. Alternate Formulation:最小截量问题

  • 把网络分割为两个成分的弧的最小集合,其中一个成分包含 s s s 点,另一个包含 t t t
  • 一般包含 s s s 点的成分中的节点集合用 V V V 表示,包含 t t t 点的成分中的节点集合用 V ˉ \bar{V} Vˉ 表示
  • 截量集容量是指截量集中前向弧的容量之和:
    C ( V , V ˉ ) = ∑ i ∈ V j ∈ V ˉ c i j C(V, \bar{V})=\sum_{\substack{i \in V \\ j \in \bar{V}}} c_{i j} C(V,Vˉ)=iVjVˉcij

福特-富克森定理:网络的最大流等于最小截量集容量。

从原始图中“减去”最大流路径,得到下图:

在这里插入图片描述

标记从 s 到达的所有节点——调用可到达节点集 A:

在这里插入图片描述
将这些节点和其他节点分开:

在这里插入图片描述

从图中删除红色的边,使得删除这些边后,没有从 s 到 t 的路径:

在这里插入图片描述

相应的最大流量路径为:
− s → a → b → t : 11 − s → c → a → b → t : 1 − s → c → d → b → t : 7 − s → c → d → t : 4 \begin{aligned} & -s \rightarrow a \rightarrow b \rightarrow t: 11 \\ & -s \rightarrow c \rightarrow a \rightarrow b \rightarrow t: 1 \\ & -s \rightarrow c \rightarrow d \rightarrow b \rightarrow t: 7 \\ & -s \rightarrow c \rightarrow d \rightarrow t: 4 \end{aligned} sabt:11scabt:1scdbt:7scdt:4

三、Ford-Fulkerson 算法

在1962年,L.R.Ford和D.R.Fulkerson发明了一种解决最大流量问题的有效方法。它是一种沿着由起点到终点的路径逐步增加流量的通用方法,因此它也是同类算法的基础。在经典文献中它被称为Ford-Fulkerson算法,但它也被称为增广路径算法。

Ford-Fulkerson最大流量算法: 网络中的初始流量为零,沿着任意从起点到终点(且不含有饱和的正向边或是空逆向边)的增广路径增大流量,直到网络中不存在这样的路径为止。

1. 导入库

from collections import defaultdict

2. 初始化残差图

初始化残差图(residual graph)以及行数 ROW。

	def __init__(self, graph):
		self.graph = graph # 残差图
		self. ROW = len(graph)
		# self.COL = len(gr[0])

3. 定义查找增广路径

使用广度优先搜索来找到从源点 s 到汇点 t 的一条增广路径,同时更新父节点数组 parent。

	def BFS(self, s, t, parent):
		visited = [False]*(self.ROW)
		queue = []

		queue.append(s)
		visited[s] = True

		while queue:
			u = queue.pop(0)
			for ind, val in enumerate(self.graph[u]):
				if visited[ind] == False and val > 0:
					queue.append(ind)
					visited[ind] = True
					parent[ind] = u
					if ind == t:
						return True
		return False

4. 定义循环

在 FordFulkerson 方法中,使用 while 循环来不断寻找增广路径,并更新残差图直到没有增广路径为止。

	def FordFulkerson(self, source, sink):
		parent = [-1]*(self.ROW)
		max_flow = 0 

		while self.BFS(source, sink, parent) :
			path_flow = float("Inf")
			s = sink
			while(s != source):
				path_flow = min (path_flow, self.graph[parent[s]][s])
				s = parent[s]

			max_flow += path_flow
			v = sink
			while(v != source):
				u = parent[v]
				self.graph[u][v] -= path_flow
				self.graph[v][u] += path_flow
				v = parent[v]

		return max_flow

5. 程序运行

from collections import defaultdict

class Graph:

	def __init__(self, graph):
		self.graph = graph
		self. ROW = len(graph)


	def BFS(self, s, t, parent):
		visited = [False]*(self.ROW)
		queue = []

		queue.append(s)
		visited[s] = True

		while queue:
			u = queue.pop(0)
			for ind, val in enumerate(self.graph[u]):
				if visited[ind] == False and val > 0:
					queue.append(ind)
					visited[ind] = True
					parent[ind] = u
					if ind == t:
						return True
		return False
			
			
	def FordFulkerson(self, source, sink):
		parent = [-1]*(self.ROW)
		max_flow = 0 

		while self.BFS(source, sink, parent) :
			path_flow = float("Inf")
			s = sink
			while(s != source):
				path_flow = min (path_flow, self.graph[parent[s]][s])
				s = parent[s]

			max_flow += path_flow
			v = sink
			while(v != source):
				u = parent[v]
				self.graph[u][v] -= path_flow
				self.graph[v][u] += path_flow
				v = parent[v]

		return max_flow



graph = [[0, 16, 13, 0, 0, 0],
		[0, 0, 10, 12, 0, 0],
		[0, 4, 0, 0, 14, 0],
		[0, 0, 9, 0, 0, 20],
		[0, 0, 0, 7, 0, 4],
		[0, 0, 0, 0, 0, 0]]

g = Graph(graph)

source = 0; sink = 5

print ("The maximum possible flow is %d " % g.FordFulkerson(source, sink))

运行结果为:

The maximum possible flow is 23

四、其它发现

Edmonds和Karp发明的另一种Ford-Fulkerson算法的实现是优先处理能够将流量增大最多的增广路径。对于这种(以及其他一些)方法,可以通过稍加修改Dijkstra的最短路径算法、由优先队列得到剩余容量最大的正向边或是流量最大的逆向边来实现。或者也可以寻找最长增广路径,或是随机选择增广路径。

各种最大流量算法的分析仍然是一个有趣而活跃的研究领域。从理论角度来说,我们已经得到了各种最大流量算法在最坏情况下的上界,但这些上界大多远远高于实际应用中所观察到的真实成本,而且也比较小的下界(线性级别)高出许多。

“最大流量算法的实际应用仍然既是一门艺术也是一门科学。它的艺术之处在于为特定的应用场景选择最有效的策略;它的科学之处在于对问题本质的理解。”

参考文献

  1. Derigs U, Meier W. Implementing Goldberg’s max-flow-algorithm—A computational investigation[J]. Zeitschrift für Operations Research, 1989, 33(6): 383-403.
  2. Ahuja R K, Kodialam M, Mishra A K, et al. Computational investigations of maximum flow algorithms[J]. European Journal of Operational Research, 1997, 97(3): 509-542.
  3. Cherkassky B V, Goldberg A V. On implementing push-relabel method for the maximum flow problem[C]//International Conference on Integer Programming and Combinatorial Optimization. Springer, Berlin, Heidelberg, 1995: 157-171.
  4. Thomas H. Cormen,Charles E. Leiserson,Ronald L. Rivest,Clifford Stein.算法导论. 美国.麻省理工学院出版社.2009

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JAVA编程思想-第 4 章 初始化和清除

第 4 章 初始化和清除 “随着计算机的进步&#xff0c;‘不安全’的程序设计已成为造成编程代价高昂的罪魁祸首之一。” “初始化”和“清除”是这些安全问题的其中两个。许多 C 程序的错误都是由于程序员忘记初始化一个变量 造成的。对于现成的库&#xff0c;若用户不知道如何…

【RL】强化学习求解JSP(作业车间调度问题)

JSP&#xff08;Job Shop Scheduling Problem&#xff09;是一种经典的组合优化问题&#xff0c;它的目标是在一组机器上安排一组工件的加工顺序&#xff0c;使得完成所有工件所需的最短时间&#xff08;Cmax&#xff09;最小。JSP 是一个 NP-hard 问题&#xff0c;即没有已知的…

深度解析Sora的核心技术

Sora要解决的核心问题 Sora面临的挑战是将不同类型的视觉信息&#xff0c;如视频、文本、图像和声音等&#xff0c;整合为一种共同的表征形式。这种转换是实现统一训练过程的关键&#xff0c;旨在将各类数据集中到一个训练框架中&#xff0c;以便于进行大规模的统一学习。简而…

机器学习 深度学习资料 资源machine learning

Kaggle入门&#xff0c;看这一篇就够了 - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/25686876 day1-1.什么是机器学习_哔哩哔哩_bilibiliday1-1.什么是机器学习是10天学会机器学习从入门到深度学习的第1集视频&#xff0c;该合集共计62集&#xff0c;视频收藏或关注UP主&a…

3.网络游戏逆向分析与漏洞攻防-游戏启动流程漏洞-游戏启动流程的分析

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;项目搭建 首先下图红框里是游戏启动的程序 游戏启动之后的名字&#xff08;fxgame.exe&#xff09; 一般游戏启动的架构&#xff1a; 第一种&#xff1a;登录器程序启动游戏主程序&#xff0c;然后游…

【快速搞定Webpack5】基本配置及开发模式介绍(二)

在开始使用webpack之前么&#xff0c;我们需要对Webpack的配置有一定的认识。 一、5大核心概念 1. enty&#xff08;入口&#xff09; 指示webpack从哪个文件开始打包 2. output&#xff08;输出&#xff09; 指示webpack打包完的文件输出到哪里去&#xff0c;如何命名等 …

说一下 JVM 有哪些垃圾回收算法?

一、标记-清除算法 标记无用对象&#xff0c;然后进行清除回收。 标记-清除算法&#xff08;Mark-Sweep&#xff09;是一种常见的基础垃圾收集算法&#xff0c;它将垃圾收集分为两个阶段&#xff1a; 标记阶段&#xff1a;标记出可以回收的对象。清除阶段&#xff1a;回收被标…

【C++】C++11下线程库

C11下线程库 1. thread类的简单介绍2.线程函数参数3.原子性操作库(atomic)4.mutex的种类5. RAII风格加锁解锁5.1Lock_guard5.2unique_lock 6.condition_variable 1. thread类的简单介绍 在C11之前&#xff0c;涉及到多线程问题&#xff0c;都是和平台相关的&#xff0c;比如wi…

Nginx服务介绍与部署配置

目录 一、Nginx相关介绍 1. 概述 2. 优缺点 3. 零拷贝技术 4. I/O模型相关概念 5. 网络I/O模型 5.1 阻塞型I/O模型 5.2 非阻塞型I/O模型 5.3 多路复用I/O型 5.4 信号驱动式I/O模型 5.5 异步I/O模型 6. 事件驱动模型 7. Nginx与Apache区别 二、Nginx部署和使用 1…

网贷大数据查询多了对征信有影响吗?

网贷大数据在日常的金融借贷中起到很重要的风控作用&#xff0c;不少银行已经将大数据检测作为重要的风控环节。很多人在申贷之前都会提前了解自己的大数据信用情况&#xff0c;那网贷大数据查询多了对征信有影响吗?本文带你一起去看看。 首先要说结论&#xff1a;那就是查询网…

ubuntu 22.04 图文安装

ubuntu 22.04.3 live server图文安装 一、在Vmware里安装ubuntu 22.04.3 live server操作系统 选择第一个选项开始安装 选择English语言 选择中间选项不更新安装&#xff0c;这是因为后续通过更换源之后再更新会比较快 键盘设计继续选择英文&#xff0c;可以通过语言选择…

单链表(上)

1. 链表的概念 概念&#xff1a;链表是一种物理存储结构上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表 中的指针链接次序实现的。 链表的结构也可以想像为一列火车&#xff0c;每节车厢都是一个成员&#xff0c;它们互补影响&#xff0c;但又通过一个装…

时间获取、文件属性获取 2月20日学习笔记

执行两次代码&#xff0c;打印出两次执行过程中新增的文件及删除的文件 #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #include <dirent.h>#def…

Redis篇----第十一篇

系列文章目录 文章目录 系列文章目录前言一、Redis 如何做内存优化?二、Redis 回收进程如何工作的?三、都有哪些办法可以降低 Redis 的内存使用情况呢?四、Redis 的内存用完了会发生什么?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下…

LabVIEW风力机智能叶片控制系统

​LabVIEW风力机智能叶片控制系统 介绍了一种风力机智能叶片控制系统的开发。通过利用LabVIEW软件与CDS技术&#xff0c;该系统能够实时监测并调整风力机叶片的角度&#xff0c;优化风能转换效率。此项技术不仅提高了风力发电的稳定性和效率&#xff0c;而且为风力机的智能化管…

Pandas时间序列数据补全

一、问题 时间序列数据缺失&#xff0c;将其补全。 如下图所示&#xff0c;数据存在缺失秒级的情况 二、方法 1、需要将时间戳字段设置成 df 的索引 2、使用df.resample()方法 (1)上采样&#xff08;将上一条数据作为当前缺失数据&#xff09; resample()中的参数&#x…

内核移植学习

内核移植 内核移植就是指将RT-Thread内核在不同的芯片架构、不同的板卡上运行起来。 移植可分为CPU架构移植和BSP板级支持包移植两部分。 CPU架构移植 在嵌入式领域有多种不同CPU架构&#xff0c;例如Cortex-M、ARM920T、MIPS32、RISC-V等等。 为了使RT-Thread能够在不同C…

【软件架构】01-架构的概述

1、定义 软件架构就是软件的顶层结构 RUP&#xff08;统一过程开发&#xff09;4 1 视图 1&#xff09;逻辑视图&#xff1a; 描述系统的功能、组件和它们之间的关系。它主要关注系统的静态结构&#xff0c;包括类、接口、包、模块等&#xff0c;并用于表示系统的组织结构…

Android基础Adapter适配器详解

一、概念 Adapter是后端数据和前端显示UI的适配器接口。常见的View如ListView、GridView等需要用到Adapter. BaseAdapter&#xff1a;抽象类&#xff0c;实际开发中继承这个类并且重写相关方法&#xff0c;用得最多的一个Adapter&#xff01; ArrayAdapter&#xff1a;支持泛型…

Gradle统一管理依赖

背景 随着项目越来越大&#xff0c;module 越来越多&#xff0c;依赖的库也越来越多&#xff0c;依赖管理也越来越混乱。 我们一般会有以下需求&#xff1a; 1. 项目依赖统一管理&#xff0c;在单独文件中配置 2. 不同 Module 中的依赖版本号统一 管理 Gradle 依赖 说明&a…