【图论】网络流——最大流和最小费用流

article/2025/9/28 19:49:06

【图论】网络流——最大流和最小费用流

文章目录

    • 【图论】网络流——最大流和最小费用流
      • 1. 最大流问题
        • 1.1 基本概念
        • 1.2 寻求最大流的算法(Ford-Fulerson)
        • 1.3 matlab求最大流
      • 2. 最小流问题
        • 2.1 基本概念
        • 2.2 求最小流的迭代算法
        • 2.3 matlab 求最大费用最小流

1. 最大流问题

主要解决系统中的流量问题:如公路系统中的车辆流、物资调配系统中的物资流、金融系统中的现金流等。

这些问题都可以归结为网络流问题,如何安排使流量最大即最大流问题


什么是最大流?

如左图能输送两份的水,是最大流;右图只能输送一份的水,不是最大流

在这里插入图片描述

1.1 基本概念

网络:图 D = ( V , A , C ) D=(V,A,C) D=(V,A,C)

  • V V V :点集。其中 v s v_s vs 为发点,只有发出的弧; v t v_t vt 为收点,该点只有进入的弧;其余的点为中间点;
  • A A A: 弧集。对于每一条弧 ( v i , v j ) ∈ A (v_i,v_j)\in A (vi,vj)A
  • C C C:容量集。每一条弧的容量 c ( v i , v j ) > = 0 c(v_i,v_j)>=0 c(vi,vj)>=0(或简记为 c i j c_{ij} cij),其中 C = { c i j } C=\{c_{ij}\} C={cij}
  • f = { f i j } = { f ( v i , v j ) } f=\{f_{ij}\}=\{f(v_i,v_j)\} f={fij}={f(vi,vj)}:弧 ( v i , v j ) (v_i,v_j) (vi,vj)上的流量

可行流:

(1) 容量限制条件: 0 ≤ f i j ≤ c i j 0\leq f_{ij} \leq c_{ij} 0fijcij

(2) 平衡条件:

  • 中间点:流出量 = 流入量   ∑ j : ( v i , v j ) ∈ A f i j − ∑ k : ( v k , v i ) ∈ A f k i = 0 ; \sum_{j:\left(v_{i}, v_{j}\right) \in A} f_{i j}-\sum_{k:\left(v_{k}, v_{i}\right) \in A} f_{k i}=0 ; j:(vi,vj)Afijk:(vk,vi)Afki=0;
  • 发点: ∑ j : ( v s , v j ) ∈ A f s j = v \sum_{j:\left(v_{s}, v_{j}\right) \in A} f_{s j}=v j:(vs,vj)Afsj=v
  • 收点: ∑ k : ( v k , v t ) ∈ A f k t = v \sum_{k_{:}\left(v_{k}, v_{t}\right) \in A} f_{k t}=v k:(vk,vt)Afkt=v

式中:v称为这个可行流的流量,即发点的净输出量。


最大流问题可以写为如下的线性规划模型:

max ⁡ v , s. t.  { ∑ j : ( v s , v j ) ∈ A f s j = v , ∑ j : ( v i , v j ) ∈ A f i j − ∑ k : ( v k , v i ) ∈ A f k i = 0 , i ≠ s , t , ∑ k : ( v k , v t ) ∈ A f k t = v , 0 ⩽ f i j ⩽ c i j , ∀ ( v i , v j ) ∈ A . \begin{array}{l} \max v, \\ \text { s. t. }\left\{\begin{array}{ll} \sum_{j:\left(v_{s}, v_{j}\right) \in A} f_{s j}=v, \\ \sum_{j:\left.(v_i, v_{j}\right)\in A} f_{i j}-\sum_{k:\left(v_{k}, v_{i}\right) \in A} f_{k i}=0, & i \neq s, t, \\ \sum_{k:\left(v_{k}, v_{t}\right) \in A} f_{k t}=v, & \\ 0 \leqslant f_{i j} \leqslant c_{i j}, & \forall\left(v_{i}, v_{j}\right) \in A . \end{array}\right. \end{array} maxv, s. t.  j:(vs,vj)Afsj=v,j:(vi,vj)Afijk:(vk,vi)Afki=0,k:(vk,vt)Afkt=v,0fijcij,i=s,t,(vi,vj)A.



1.2 寻求最大流的算法(Ford-Fulerson)

步骤:

  1. 建立残差图, 将残差图的容量初始化

  2. 当增广路径可以被找到时一直循环以下步骤:

    a. 在残差图上一直寻找增广路径
    b. 在增广路径上找到容量最小值 x x x
    c. 更新残差图上的容量: 增广路径上的容量 = 增广路径上的容量 − x 增广路径上的容量 =增广路径上的容量 - x 增广路径上的容量=增广路径上的容量x
    d. 添加反向路径。(沿着增广路径的反方向,所有边的权重为x。)

示例:

  1. 初始化: 左图为原图,右图为构建的与原图一致的残差图。

在这里插入图片描述


  1. 第一轮循环:

① 找到如图红线的增广路径

② 可以看到整条路上容量的最大值为3,因此将路径上所有边的容量减去3

③ 去除容量为0的边,并添加值为3的反向路径
在这里插入图片描述


  1. 第二轮循环

① 找到如图红线的增广路径

② 可以看到整条路上容量的最大值为1,因此将路径上所有边的容量减去1

③ 去除容量为0的边,并添加值为1的反向路径

在这里插入图片描述

④ 合并反向路径的容量值

在这里插入图片描述

  1. 第三轮循环

① 找到如图的增广路径 (注意:这里就体现了增加的反向边的重要性了,如果没有反向边,是找不到从起点到终点的增广路径的

② 可以看到整条路上容量的最大值为1,因此将路径上所有边的容量减去1

③ 去除容量为0的边,并添加值为1的反向路径

在这里插入图片描述

④ 合并反向路径的容量值

在这里插入图片描述

  1. 第四轮循环

发现没有水流流入 v 3 v_3 v3,因此没有水流从起点到终点,循环终止。

在这里插入图片描述

  1. 计算容量

最大流 = 3 + 1 + 1 = 5 最大流=3+1+1=5 最大流=3+1+1=5

代码

import copy
from collections import dequedef hasPath(Gf, s, t, path):# BFS algorithmV = len(Gf)visited = list(range(V))for i in range(V):visited[i] = Falsevisited[s] = Truequeue = deque([s])	# 起点入队while queue:temp = queue.popleft()	# 队头元素if temp == t:	# 如果到达了终点return Truefor i in range(V):	# 遍历队头元素的每个邻点# 如果零点没有被访问且流量为正向if not visited[i] and (Gf[temp][i] > 0):queue.append(i)visited[i] = Truepath[i] = temp   # 节点i的父节点为tempreturn visited[t]def max_flow(graph, s, t):maxFlow = 0Gf = copy.deepcopy(graph)V = len(Gf)path = list(range(V))# 只要有增广路径就一直循环while hasPath(Gf, s, t, path):min_flow = float('inf')# 不断利用道路上的父节点回溯,找到增广路径上的容量最小值v = twhile v != s:	u = path[v]min_flow = min(min_flow, Gf[u][v])v = path[v]print(min_flow)# 增广路径上的容量减去最小值,并添加反向路径v = twhile v != s:u = path[v]Gf[u][v] -= min_flowGf[v][u] += min_flowv = path[v]maxFlow += min_flowreturn maxFlowM=0
capacity = [
[0,16,13,M,M,M],
[M,0,10,12,M,M],
[M,4,0,M,14,M],
[M,M,9,0,M,20],
[M,M,M,7,0,4],
[M,M,M,M,M,0]
]flow = max_flow(capacity, 0, 5)
print("flow =", flow)

1.3 matlab求最大流

如图求①到⑧的最大流
在这里插入图片描述

a=zeros(8);a(1,[2:4])=[6,4,5];
a(2,[3,5,6])=[3,9,9];
a(3,[4:7])=[5,6,7,3];
a(4,[3,7])=[2,5];
a(5,8)=12;
a(6,[5,8])=[8,10];
a(7,[6,8])=[4,15];
G=digraph(a);
H=plot(G,'EdgeLabel',G.Edges.Weight);
[M,F]=maxflow(G,1,8);
F.Edges,highlight(H,F);

在这里插入图片描述


2. 最小流问题

2.1 基本概念

在许多实际问题中,往往还要考虑网络流上的费用问题。例如在运输问题中,人们总是希望在完成运输任务时,寻求一个运输费用最小的方案。

最小流问题可以写为如下的线性规划模型:

b i j b_{ij} bij为弧 ( v i , v j ) (v_i,v_j) (vi,vj)上的单位费用

min ⁡ ∑ j : ( v i , v j ) ∈ A f i j b i j s. t.  { ∑ j : ( v s , v j ) ∈ A f s j = v , ∑ j : ( v i , v j ) ∈ A f i j − ∑ k : ( v k , v i ) ∈ A f k i = 0 , i ≠ s , t , ∑ k : ( v k , v t ) ∈ A f k t = v , 0 ⩽ f i j ⩽ c i j , ∀ ( v i , v j ) ∈ A . \begin{array}{l} \min \sum_{j:\left(v_{i}, v_{j}\right) \in A} f_{i j}b_{ij} \\ \text { s. t. }\left\{\begin{array}{ll} \sum_{j:\left(v_{s}, v_{j}\right) \in A} f_{s j}=v, \\ \sum_{j:\left.(v_i, v_{j}\right)\in A} f_{i j}-\sum_{k:\left(v_{k}, v_{i}\right) \in A} f_{k i}=0, & i \neq s, t, \\ \sum_{k:\left(v_{k}, v_{t}\right) \in A} f_{k t}=v, & \\ 0 \leqslant f_{i j} \leqslant c_{i j}, & \forall\left(v_{i}, v_{j}\right) \in A . \end{array}\right. \end{array} minj:(vi,vj)Afijbij s. t.  j:(vs,vj)Afsj=v,j:(vi,vj)Afijk:(vk,vi)Afki=0,k:(vk,vt)Afkt=v,0fijcij,i=s,t,(vi,vj)A.

v = 最大流 v m a x v=最大流v_{max} v=最大流vmax时,本问题就是最小费用最大流问题;如果 v > v m a x v>v_{max} v>vmax,则本问题无解

2.2 求最小流的迭代算法

(1)求出从出发点到收点的最小费用流 μ ( v x , v t ) \mu (v_x,v_t) μ(vx,vt)。(类似求最短路)

(2)对该通路 μ ( v x , v t ) \mu (v_x,v_t) μ(vx,vt)分配可能的最大流量 f ˉ = min ⁡ ( v i , v j ) ∈ μ ( v s , v t ) { c i j } \bar f=\min_{(v_i,v_j)\in \mu(v_s,v_t)}\{c_{ij}\} fˉ=min(vi,vj)μ(vs,vt){cij},并让通路上所有边的容量对应减少 f ˉ \bar f fˉ。并将通路上的饱和边的单位费用改为 ∞ \infty .

(3)作该通路 μ ( v s , v t ) \mu (v_s,v_t) μ(vs,vt)所有边 ( v i , v j ) (v_i,v_j) (vi,vj)的反向边 ( v j , v i ) (v_j,v_i) (vj,vi)。令 c j i = f ˉ , b j i = − b i j c_{ji}=\bar f,b_{ji}=-b_{ij} cji=fˉbji=bij

(4)重复(1)~(3),直到发点到收点的全部流量等于 v v v为止,或找不到增广路到 v v v


2.3 matlab 求最大费用最小流

如图带有运费的网络,求从 v s v_s vs v t v_t vt的最小费用最大流,其中弧上权重的第1个数字是网络的容量,第2个数字是网络的单位运费。

在这里插入图片描述

NN = cellstr(strcat('v',int2str([2:5]')));  % 构造中间节点
NN = {'vs',NN{:},'vt'}; % 添加发点和收点
L ={'vs','v2',5,3;'vs','v3',3,6;'v2','v4',2,8;'v3','v2',1,2;'v3','v5',4,2;'v4','v3',1,1;'v4','v5',3,4;'v4','vt',2,10;'v5','vt',5,2};
G=digraph;G=addnode(G,NN);
G1=addedge(G,L(:,1),L(:,2),cell2mat(L(:,3)));
[M,F]=maxflow(G1,'vs','vt');    % 求最大流G2=addedge(G,L(:,1),L(:,2),cell2mat(L(:,4)));
c = full(adjacency(G1,'weighted'));
b = full(adjacency(G2,'weighted'));
f = optimvar('f',6,6,'LowerBound',0);
prob=optimproblem;
prob.Objective = sum(sum(b.*f));
con1 = [sum(f(1,:))==Msum(f(:,[2:end-1]))'==sum(f([2:end-1],:),2)sum(f(:,end))==M];
prob.Constraints.con1=con1;
prob.Constraints.con2=f<=c;
[sol,fval,flag,out ] = solve(prob);
ff=sol.f;   % 显示最小费用最大流对应的矩阵

图中对应的就是最小费用最大流:

在这里插入图片描述

学习对象:【13-2: Ford-Fulkerson Algorithm 寻找网络最大流】


http://chatgpt.dhexx.cn/article/4B0OaXMa.shtml

相关文章

网络流(2)-----最小费用最大流(附带讲解SPFA算法)

一.最小费用最大流&#xff08;简称费用流&#xff09;概念 1.什么是费用流问题 上篇文章我们讲解了最大流问题&#xff0c;那什么是最小费用最大流呢&#xff1f;听名字就可以看出&#xff0c;我们要在满足最大流的同时找到达成最大流的最小费用。对于一个网络流&#xff0c…

最小费用最大流问题详解

最小费用最大流问题 一、问题描述 在网络中求一个最大流f&#xff0c;使流的总输送费用最小。 b ( f ) ∑ ( v i , v j ) b i j f i j b(f) \sum\limits_{(v_i,v_j)} b_{ij} f_{ij} b(f)(vi​,vj​)∑​bij​fij​ ) &#xff08; b i j b_{ij} bij​ 表示弧 ( v i , v j…

最小费用最大流问题与算法实现(Bellman-Ford、SPFA、Dijkstra)

摘要 今日&#xff0c;对最小费用最大流问题进行了一个简单的研究&#xff0c;并针对网上的一些已有算法进行了查找和研究。博客和资料很多&#xff0c;但是留下的算法很多运行失败、出错&#xff0c;或者意义不明。这里&#xff0c;个人对其中的Bellman-Ford、SPFA、改进的Di…

如何区分冲突域和广播域?

举个例子&#xff0c;原始社会的人都生活在山洞里&#xff0c;每个人都住在自己的山洞里&#xff0c;洞穴的中间只有一个狭长的走廊可以出去&#xff0c;平时出去玩&#xff0c;大哥都会喊一嗓子&#xff0c;有人出去打猎不&#xff0c;所有人都听得到&#xff0c;这就是一个广…

冲突域和广播域区别

一、区别 1、广播域就是说如果站点发出一个广播信号后能接收到这个信号的范围。通常来说一个局域网就是一个广播域。冲突域指一个站点向另一个站点发出信号。除目的站点外&#xff0c;有多少站点能收到这个信号。这些站点就构成一个冲突域。 2、冲突域通过集线器连接&#xf…

冲突域和广播域区别,集线器、交换机和路由器对比

冲突域 我们把以太网想象为对讲机&#xff0c;电脑想象为使用对讲机的人&#xff0c;数据传输想象为使用对讲机说话。现在一群人打真人CS&#xff0c;两个及以上的人同时通过对讲机说话&#xff0c;就听不清在说什么了&#xff0c;这就是冲突。对讲机通道只能一人单独使用。对…

冲突域和广播域; 集线器、交换机以及路由器比较

转自https://blog.csdn.net/gui951753/article/details/79402528#1%E5%B7%A5%E4%BD%9C%E5%B1%82%E6%AC%A1%E4%B8%8D%E5%90%8C 目录 冲突域和广播域 联网中继设备 集线器&#xff08;hub&#xff09; 交换机(switch) 路由器(route) 三者的异同 冲突域和广播域 在介绍这三…

交换机基础原理,冲突域和广播域

交换机的基本定义 提供了大量的接入端口&#xff0c;能够很好的满足大量用户接入到网络中的需求。 在OSI模型的二层&#xff0c;数据链路层&#xff1b; 可以识别数据包中的MAC地址信息&#xff0c;根据MAC地址进行转发数据&#xff0c;并且会将这些MAC地址与对应的端口记录在…

冲突域和广播域的区分

一、概念理解&#xff1a; 1、冲突域&#xff08;物理分段&#xff09;&#xff1a; 连接在同一导线上的所有工作站的集合&#xff0c;或者说是同一物理网段上所有节点的集合或以太网上竞争同一带宽的节点集合。这个域代表了冲突在其中发生并传播的区域&#xff0c;这个区域可…

冲突域和广播域的区别

冲突域 冲突域指的是会产生冲突的最小范围&#xff0c;在计算机和计算机通过设备互联时&#xff0c;会建立一条通道&#xff0c;如果这条通道只允许瞬间一个数据报文通过&#xff0c;那么在同时如果有两个或更多的数据报文想从这里通过时就会出现冲突了。 冲突域的大小可以衡…

冲突域和广播域

冲突域&#xff1a; 冲突域是信道的争抢&#xff0c;信道只有一条&#xff0c;A在使用&#xff0c;B就不可以使用&#xff0c;这样就会产生冲突&#xff0c;这就是冲突域的产生 在一个信道上的所有主机组成一个冲突域&#xff0c;划分网络越小越好&#xff0c;不会引起很大的冲…

如何理解冲突域和广播域?(转)

如何理解冲突域和广播域&#xff1f;&#xff08;转&#xff09; 转自&#xff1a;http://blog.sina.com.cn/s/blog_7e8dec240102wyio.html 网上看到的好文章&#xff0c;整理下来&#xff0c;方便复习&#xff0c;侵删 1、冲突域&#xff1a; 【定义】在同一个冲突域中的每…

设备划分冲突域和广播域

冲突域是一种物理分段&#xff0c;指连接到同一导线上所有工作站的集合、同一物理网段上所有节点的集合或是以太网上竞争同一带宽节点的集合。冲突域表示冲突发生并传播的区域&#xff0c;这个区域可以被认为是共享段。在OSI模型中&#xff0c;冲突域被看作是OSI第一层的概念&a…

HCIA—冲突域与广播域(详解 + 区别)

目录 一、冲突域&#xff1a; &#xff08;1&#xff09;HUB组网&#xff1a; &#xff08;2&#xff09;冲突域 概述 特点&#xff1a; 二、广播域&#xff1a; &#xff08;1&#xff09;广播域 概述特点&#xff1a; 三、冲突域 与 广播域的区别与联系&#xff1a; 一…

网络基础之冲突域和广播域

温故&#xff1a; 前面的几天 &#xff0c;主要讲了OSI网络七层的相关知识&#xff0c;着重的分析了每一层所具备的功能和服务&#xff0c;在这里我再次强调一遍&#xff1a;功能指的是本层的作用&#xff0c;服务指的是本层能为上层提供的业务&#xff0c;至于协议则是定义了每…

广播域和冲突域

在准备软考的时候将广播域看成了广域网,结果就错了一道题,这篇文章就从这道错题开始... 1.广播域和冲突域的定义 广播域:网络中能接受任一设备发出的广播帧的设备的集合. 冲突域:在同一个网络内,如果任意两台计算机在同时通信是会发生冲突,那么它们所组成的网络就是一个冲突域…

计算机网络 —— 冲突域和广播域

一、概念 &#xff08;1&#xff09;冲突域 定义&#xff1a;同一时间内只能有一台设备发送信息的范围。 分层&#xff1a;基于OSI的第一层物理层 设备&#xff1a;第二层设备能隔离冲突域&#xff0c;比如Switch。交换机能缩小冲突域的范围&#xff0c;交换接的每一个端口就…

冲突域与广播域

冲突域是一种物理分段&#xff0c;指连接到同一导线上所有工作站的集合、同一物理网段上所有节点的集合或是以太网上竞争同一带宽节点的集合。冲突域表示冲突发生并传播的区域&#xff0c;这个区域可以被认为是共享段。在OSI模型中&#xff0c;冲突域被看作是OSI第一层的概念&a…

向上取整的代码写法

如何实现向上取整 例如&#xff0c;x / n 上取整&#xff0c;代码如下 v (x (n - 1)) / n 下取整呢&#xff1f;haha v x / n 例题 森林中&#xff0c;每个兔子都有颜色。其中一些兔子&#xff08;可能是全部&#xff09;告诉你还有多少其他的兔子和自己有相同的颜色。我们…

php函数向上取整,php向上取整用什么函数

我们经常用到的PHP取整函数&#xff0c;主要是&#xff1a;ceil&#xff0c;floor&#xff0c;round&#xff0c;intval。 ceil -- 进一法取整说明float ceil ( float value ) 返回不小于 value 的下一个整数&#xff0c;value 如果有小数部分则进一位。ceil() ... 在PHP中&…