💕个人主页:Puszy-优快云博客💕
🎉 欢迎关注:👍点赞 📣留言 😍收藏 💖 💖 💖
赌书消得泼茶香,当时只道是寻常。 –– 《人民日报》
🌈🌈🌈往期精选:
💖【数学建模】主成分分析(PCA)详解:从理论到实践的全面指南-优快云博客
💖【数学建模】数据拟合与插值技术全解析:从线性插值到Logistic模型实战-优快云博客
目录
【数学建模】图论模型:从Dijkstra算法到最小费用最大流实战
💖引言
在我们这个高度互联的世界中,从社交网络到交通系统,从生物化学网络到互联网,图论模型无处不在。图论,这一数学分支,通过节点和边的简单概念,为我们提供了一种强大的工具,用以理解和分析复杂系统中的关系与结构。
在本篇博客中,为了更好地理解图论模型,我将通过具体的题目来驱动对模型原理的探讨。例如,最短路径问题可以通过Dijkstra算法解决,该算法通过逐步扩展已知的最短路径,最终找到从起点到终点的最短路径。
📚一、Dijkstra算法
🚀1.1、概念
迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。
🚀1.2、核心思想
Dijkstra 算法的核心思想是 贪心策略 和 松弛操作,适用于 边权重非负 的有向或无向图。是其核心原理和思想的详细解释如下:
-
逐步逼近最优解
从起点出发,逐步向外扩展,每次选择当前已知 最短路径 的节点,并更新其邻居节点的最短路径值。 -
贪心选择性质
每次选择当前距离起点最近的未处理节点,假设该节点的当前最短路径已经是全局最优解(基于非负权重的假设)。 -
动态更新(松弛操作)
每当发现更短的路径时,更新节点的最短距离值。
🚀1.3、重要概念介绍
邻接矩阵概念介绍:

流量矩阵概念介绍:

| 矩阵类型 | 元素含义 | 用途 |
|---|---|---|
| 邻接矩阵 | 表示边的存在性或权重 | 描述图的结构 |
| 流量矩阵 | 表示边实际通过的流量 | 分析最大流的具体分配 |
📚二、案例分析
🚀2.1、最短路径类问题
📘2.1.1、题目一:企业设备更新计划
某企业使用一台设备,在每年年初都要决定是购置新设备还是继续使用旧的。购置新设备要支付一定的购置费,使用旧设备则要支付维修费。试制定一个五年的设备更新计划,使得总支付费用最少。己知该设备在各年年初的价格为:
| 第一年 | 第二年 | 第三年 | 第四年 | 第五年 |
|---|---|---|---|---|
| 11 | 11 | 12 | 12 | 13 |
已知使用不同时间的设备每年维修费用为:
| 使用年数 | 0-1 | 1-2 | 2-3 | 3-4 | 4-5 |
|---|---|---|---|---|---|
| 维修费用 | 5 | 6 | 8 | 11 | 18 |
📄2.1.2、分析
可以把这个间题化为图论中的最短路问题。构造赋权有向图 ,其中顶点集
,这里
表示第
年初的时刻,
表示第 5 年末的时刻
为弧的集合,邻接矩阵
,这里
表示时刻
购置新设备使用到时刻
,购置新设备的费用和维修费用之和。则邻接矩阵
则制定总的支付费用最小的设备更新计划,就是在有向图中求从
到
的费用最短路。
🎉2.1.3、结果展示
由图可以看出,第一年购买后维修两年,到第三年,再次购买设备,维修到第五年,费用最小,即。

📈2.1.4、代码展示
import numpy as np
import networkx as nx
import pylab as plt
a=np.zeros((6,6))
a[0,1:]=[16,22,30,41,59]
a[1,2:]=[16,22,30,41]
a[2,3:]=[17,23,31]
a[3,4:]=[17,23]
a[4,5]=18
print(a)
G=nx.DiGraph(a) #构造赋权有向图,顶点编号为0,1,…,5
p=nx.shortest_path(G,0,5,weight='weight')
d=nx.shortest_path_length(G,0,5,weight='weight')
print('path=',p); print('d=',d)
plt.rc('font',size=20)
pos=nx.shell_layout(G) #设置布局
w=nx.get_edge_attributes(G,'weight')
key=range(6); s=['V'+str(i+1) for i in key]
s=dict(zip(key,s)) #构造用于顶点标注的字符字典
nx.draw(G, pos, font_weight='bold', labels=s, node_color='gray')
nx.draw_networkx_edge_labels(G, pos, edge_labels=w)
path_edges=list(zip(p, p[1:]))
nx.draw_networkx_edges(G, pos, edgelist=path_edges,
edge_color='b', width=2)
plt.show()
🚀2.2、最大费用最小流类问题
📘2.2.1、题目二:飞机行驶最优路径
在一次长距离空中演习过程中,战斗机从甲地出发,向目的地乙地飞行。由于战斗机的供油问题,因此需要在飞行一段时间后需要到特定地点进行加油,为保证不被敌军发现,每个航线的战斗机数量都有明确限制,具体单位战斗机飞行路线飞机数量与油耗如图1所示。如果你是这次演习中的指挥官,请设计一种方案,使得从甲地到乙地的战斗机数量最多,且耗油总量最少。

📄2.3.2、分析
由数量最多,且耗油总量最少,可知,明显的最大最小流问题,可以使用Python的networkx包来解决该类问题。详细分析可参考代码逻辑。
🎉2.3.3、结果展示

📈2.4.4、代码展示
import networkx as nx
import numpy as np
# 创建有向图
G = nx.DiGraph()
# 添加边以及对应的容量(战斗机数量)和费用(燃料消耗)
edges = [
(0, 1, 15, 8),
(0, 2, 10, 10),
(0, 3, 20, 15),
(1, 4, 7, 9),
(1, 5, 10, 11),
(2, 5, 8, 8),
(2, 6, 2, 6),
(3, 6, 18, 14),
(4, 7, 6, 8),
(5, 7, 16, 9),
(6, 7, 20, 10)
]
# 将边添加到图中
for u, v, capacity, cost in edges:
G.add_edge(u, v, capacity=capacity, weight=cost)
# 计算从节点0到节点7的最大流和最小费用
flow_dict = nx.max_flow_min_cost(G, 0, 7)
total_flow = sum(flow_dict[0].values())
total_cost = nx.cost_of_flow(G, flow_dict)
print(f'从节点 0 到节点 7 的最大流和最小费用')
print(f'最大流:{total_flow}')
print(f'最小费用:{total_cost}')
# 导出顶点列表
node = list(G.nodes())
n = len(node)
# 创建流量矩阵
flow_mat = np.zeros((n, n))
for i, adj in flow_dict.items():
for j, k in adj.items():
flow_mat[node.index(i), node.index(j)] = k
print("最大流的流量为:", sum(flow_mat[:, -1]))
print("最小费用最大流的流量矩阵为:\n", flow_mat)
# 找到所有路径
paths = []
for i in range(n):
for j in range(n):
if flow_mat[i, j] > 0:
paths.append((node[i], node[j], flow_mat[i, j]))
print("详细路径为:")
for path in paths:
print(f"从 {path[0]} 到 {path[1]} 的流量为 {path[2]}")
📚参考链接

1182

被折叠的 条评论
为什么被折叠?



