当前位置: 首页 > news >正文

【数学建模】——前沿图与网络模型:新时代算法解析与应用

目录

1.图与网络的基本概念

1. 无向图和有向图

2. 简单图、完全图、赋权图

3. 顶点的度

4. 子图与图的连通性

2.图的矩阵表示

1. 关联矩阵

2. 邻接矩阵

3.最短路问题

1.Dijkstra 算法

2.Floyd 算法

4.最小生成树问题

1.Kruskal 算法

2.Prim 算法

5.着色问题

6.旅行商问题

近似算法

7.网络最大流问题

Ford-Fulkerson 算法

8.计划评审方法与关键路径

9.钢管订购和运输

总结


 

ce6fbd68767d465bbe94b775b8b811db.png

731bd47804784fa2897220a90a387b28.gif

专栏:数学建模学习笔记

上一篇:【MATLAB】和【Python】进行【图与网络模型】的高级应用与分析】

本篇是对上一篇的升华,进一步学习

1.图与网络的基本概念

1. 无向图和有向图

根据PPT内容,我们知道图的基本概念包括无向图和有向图。

  • 无向图:边没有方向,表示为 (u, v) = (v, u)。
  • 有向图:边有方向,表示为 (u, v) ≠ (v, u)。

PPT中的示例图可以用以下代码进行可视化:

import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.font_manager import FontProperties# 设置中文字体
font = FontProperties(fname=r"C:\Windows\Fonts\simsun.ttc", size=15)# 无向图的邻接矩阵
A_undirected = np.array([[0, 1, 1, 0],[1, 0, 1, 1],[1, 1, 0, 1],[0, 1, 1, 0]
])# 有向图的邻接矩阵
A_directed = np.array([[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1],[1, 0, 0, 0]
])# 使用邻接矩阵创建无向图和有向图
G_undirected = nx.from_numpy_array(A_undirected)
G_directed = nx.from_numpy_array(A_directed, create_using=nx.DiGraph)# 绘制无向图
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
nx.draw(G_undirected, with_labels=True, node_color='skyblue', edge_color='black', node_size=1500, font_size=20)
plt.title('无向图', fontproperties=font)# 绘制有向图
plt.subplot(1, 2, 2)
nx.draw(G_directed, with_labels=True, node_color='lightgreen', edge_color='red', node_size=1500, font_size=20, arrows=True)
plt.title('有向图', fontproperties=font)plt.show()

代码解析

  • networkx库用于创建和操作图。
  • matplotlib库用于绘图。
  • nx.Graph()创建无向图,nx.DiGraph()创建有向图。
  • add_edges_from()方法添加边。
  • nx.draw()方法绘制图形。

2. 简单图、完全图、赋权图

  • 简单图:没有自环和重边的图。
  • 完全图:任意两个不同顶点之间都有边的图。
  • 赋权图:边上有权值的图。

PPT中的示例图可以用以下代码进行可视化:

import networkx as nx
import matplotlib.pyplot as plt
# 简单图
G_simple = nx.Graph()
G_simple.add_edges_from([(1, 2), (2, 3), (3, 4), (4, 1)])
plt.figure(figsize=(8, 6))
plt.title("Simple Graph")
nx.draw(G_simple, with_labels=True, node_color='lightgreen', node_size=2000, edge_color='black', linewidths=1, font_size=15)
plt.show()# 完全图
G_complete = nx.complete_graph(5)
plt.figure(figsize=(8, 6))
plt.title("Complete Graph")
nx.draw(G_complete, with_labels=True, node_color='lightcoral', node_size=2000, edge_color='black', linewidths=1, font_size=15)
plt.show()# 赋权图
G_weighted = nx.Graph()
G_weighted.add_weighted_edges_from([(1, 2, 0.6), (1, 3, 0.2), (2, 3, 0.8), (2, 4, 0.4)])
plt.figure(figsize=(8, 6))
plt.title("Weighted Graph")
pos = nx.spring_layout(G_weighted)
nx.draw(G_weighted, pos, with_labels=True, node_color='lightblue', node_size=2000, edge_color='black', linewidths=1, font_size=15)
labels = nx.get_edge_attributes(G_weighted, 'weight')
nx.draw_networkx_edge_labels(G_weighted, pos, edge_labels=labels)
plt.show()

 

代码解析

  • nx.complete_graph()创建完全图。
  • nx.add_weighted_edges_from()添加有权值的边。
  • nx.spring_layout()设置图的布局。
  • nx.draw_networkx_edge_labels()显示边的权值。

3. 顶点的度

  • 顶点的度:连接该顶点的边的数目。

PPT中的示例可以用以下代码展示顶点的度:

import networkx as nx
import matplotlib.pyplot as plt# 计算无向图的顶点度
G_undirected = nx.Graph()
G_undirected.add_edges_from([(1, 2), (1, 3), (2, 4), (3, 4)])
G_undirected_degree = G_undirected.degree()
plt.figure(figsize=(8, 6))
plt.title("Undirected Graph - Node Degree")
nx.draw(G_undirected, with_labels=True, node_color='skyblue', node_size=[v * 1000 for k, v in G_undirected_degree], edge_color='black', linewidths=1, font_size=15)
plt.show()# 计算有向图的顶点入度和出度
G_directed = nx.DiGraph()
G_directed.add_edges_from([(1, 2), (1, 3), (2, 4), (3, 4)])
G_directed_in_degree = G_directed.in_degree()
G_directed_out_degree = G_directed.out_degree()
plt.figure(figsize=(8, 6))
plt.title("Directed Graph - Node In-Degree")
nx.draw(G_directed, with_labels=True, node_color='skyblue', node_size=[v * 1000 for k, v in G_directed_in_degree], edge_color='black', arrows=True, linewidths=1, font_size=15)
plt.show()plt.figure(figsize=(8, 6))
plt.title("Directed Graph - Node Out-Degree")
nx.draw(G_directed, with_labels=True, node_color='skyblue', node_size=[v * 1000 for k, v in G_directed_out_degree], edge_color='black', arrows=True, linewidths=1, font_size=15)
plt.show()

代码解析

  • degree()计算无向图顶点的度。
  • in_degree()计算有向图顶点的入度。
  • out_degree()计算有向图顶点的出度。

 

4. 子图与图的连通性

  • 子图:原图的部分顶点和边组成的图。
  • 连通图:任意两个顶点之间都有路径相连的图。

PPT中的示例可以用以下代码展示子图和连通性:

import networkx as nx
import matplotlib.pyplot as plt# 子图示例
G_undirected = nx.Graph()
G_undirected.add_edges_from([(1, 2), (1, 3), (2, 4), (3, 4)])
subgraph_nodes = [1, 2, 3]
G_subgraph = G_undirected.subgraph(subgraph_nodes)
plt.figure(figsize=(8, 6))
plt.title("Subgraph")
nx.draw(G_subgraph, with_labels=True, node_color='yellow', node_size=2000, edge_color='black', linewidths=1, font_size=15)
plt.show()# 连通图示例
G_connected = nx.cycle_graph(5)
plt.figure(figsize=(8, 6))
plt.title("Connected Graph")
nx.draw(G_connected, with_labels=True, node_color='lightblue', node_size=2000, edge_color='black', linewidths=1, font_size=15)
plt.show()# 不连通图示例
G_disconnected = nx.Graph()
G_disconnected.add_edges_from([(1, 2), (3, 4)])
plt.figure(figsize=(8, 6))
plt.title("Disconnected Graph")
nx.draw(G_disconnected, with_labels=True, node_color='lightblue', node_size=2000, edge_color='black', linewidths=1, font_size=15)
plt.show()

代码解析

  • subgraph()生成子图。
  • cycle_graph()创建连通图(环图)。
  • 添加孤立的边以生成不连通图。

 

2.图的矩阵表示

1. 关联矩阵

关联矩阵用于表示图中顶点与边之间的关系。在无向图中,关联矩阵是一个 |V| × |E| 的矩阵,其中 |V| 是顶点数,|E| 是边数。矩阵中的元素 a[i][j] 表示顶点 i 是否与边 j 相连,如果相连则为 1,否则为 0。在有向图中,a[i][j] 为 -1 表示顶点 i 是边 j 的起点,为 1 表示顶点 i 是边 j 的终点。

根据PPT的描述,我们可以用以下代码展示关联矩阵:

import networkx as nx
import numpy as np# 无向图
G_undirected = nx.Graph()
G_undirected.add_edges_from([(1, 2), (1, 3), (2, 4), (3, 4)])
G_undirected_adj = nx.incidence_matrix(G_undirected).todense()
print("无向图的关联矩阵:\n", G_undirected_adj)# 有向图
G_directed = nx.DiGraph()
G_directed.add_edges_from([(1, 2), (1, 3), (2, 4), (3, 4)])
G_directed_adj = nx.incidence_matrix(G_directed, oriented=True).todense()
print("有向图的关联矩阵:\n", G_directed_adj)

代码解析

  • incidence_matrix()计算关联矩阵。
  • oriented=True用于有向图。
无向图的关联矩阵:[[1. 1. 0. 0.][1. 0. 1. 0.][0. 1. 0. 1.][0. 0. 1. 1.]]
有向图的关联矩阵:[[-1. -1.  0.  0.][ 1.  0. -1.  0.][ 0.  1.  0. -1.][ 0.  0.  1.  1.]]

2. 邻接矩阵

邻接矩阵用于表示顶点之间是否直接相连。对于一个有 n 个顶点的图,邻接矩阵是一个 n × n 的矩阵。对于无向图,如果顶点 i 与顶点 j 之间有边相连,则 a[i][j] = 1,否则 a[i][j] = 0。在赋权图中,a[i][j] 表示顶点 i 和顶点 j 之间边的权值,如果没有边则为 0 或无穷大。

根据PPT的描述,我们可以用以下代码展示邻接矩阵:

import networkx as nx# 无向图
G_undirected = nx.Graph()
G_undirected.add_edges_from([(1, 2), (1, 3), (2, 4), (3, 4)])
G_undirected_adj_matrix = nx.adjacency_matrix(G_undirected).todense()
print("无向图的邻接矩阵:\n", G_undirected_adj_matrix)# 有向图
G_directed = nx.DiGraph()
G_directed.add_edges_from([(1, 2), (1, 3), (2, 4), (3, 4)])
G_directed_adj_matrix = nx.adjacency_matrix(G_directed).todense()
print("有向图的邻接矩阵:\n", G_directed_adj_matrix)

代码解析

  • adjacency_matrix()计算邻接矩阵。
无向图的邻接矩阵:[[0 1 1 0][1 0 0 1][1 0 0 1][0 1 1 0]]
有向图的邻接矩阵:[[0 1 1 0][0 0 0 1][0 0 0 1][0 0 0 0]]

 

3.最短路问题

最短路问题是指在赋权图中,找到从源点到目标点的最短路径。常见的算法有 Dijkstra 算法和 Floyd 算法。

1.Dijkstra 算法

Dijkstra 算法用于求解单源最短路径问题,适用于所有边权值为非负的图。算法的基本思想是通过贪心策略,每次选择距离起点最近的未访问顶点,并更新其邻接顶点的距离。具体步骤如下:

  1. 初始化源点到自身的距离为 0,其余顶点的距离为无穷大。
  2. 将所有顶点加入未访问集合。
  3. 从未访问集合中选择距离起点最近的顶点 u,标记 u 为已访问。
  4. 对于 u 的每个邻接顶点 v,如果 u 到 v 的距离加上 u 到起点的距离小于 v 到起点的当前距离,则更新 v 的距离。
  5. 重复步骤 3 和 4,直到所有顶点都被访问。

Dijkstra 算法的时间复杂度为 O(V^2),对于稠密图比较适用。如果使用优先队列进行优化,时间复杂度可以降到 O(E log V)。

PPT中的示例可以用以下代码展示Dijkstra算法:

import heapqdef dijkstra(graph, start):pq = [(0, start)]distances = {vertex: float('infinity') for vertex in graph}distances[start] = 0while pq:current_distance, current_vertex = heapq.heappop(pq)if current_distance > distances[current_vertex]:continuefor neighbor, weight in graph[current_vertex].items():distance = current_distance + weightif distance < distances[neighbor]:distances[neighbor] = distanceheapq.heappush(pq, (distance, neighbor))return distancesgraph = {'A': {'B': 1, 'C': 4},'B': {'A': 1, 'C': 2, 'D': 5},'C': {'A': 4, 'B': 2, 'D': 1},'D': {'B': 5, 'C': 1}
}distances = dijkstra(graph, 'A')
print("Dijkstra's Algorithm Output:", distances)

代码解析

  • heapq用于实现优先队列。
  • dijkstra()函数实现了Dijkstra算法。
  • distances存储每个顶点的最短距离。

Dijkstra's Algorithm Output: {'A': 0, 'B': 1, 'C': 3, 'D': 4} 

2.Floyd 算法

Floyd 算法用于求解任意两点间的最短路径问题,适用于所有边权值为非负的图。算法的基本思想是通过动态规划,每次考虑加入一个中间顶点来更新最短路径。具体步骤如下:

  1. 初始化一个距离矩阵,直接使用图的邻接矩阵表示顶点之间的距离。
  2. 对于每个顶点 k,更新所有顶点对 (i, j) 的距离。如果 i 到 j 的距离通过顶点 k 更短,则更新距离矩阵。
  3. 重复上述步骤,直到考虑完所有顶点。

Floyd 算法的时间复杂度为 O(V^3),适用于稀疏图和需要频繁查询任意两点最短路径的情况。

PPT中的示例可以用以下代码展示Floyd算法:

def floyd_warshall(graph):nodes = list(graph.keys())distances = {node: {node2: float('infinity') for node2 in nodes} for node in nodes}for node in nodes:distances[node][node] = 0for node in graph:for neighbor in graph[node]:distances[node][neighbor] = graph[node][neighbor]for k in nodes:for i in nodes:for j in nodes:if distances[i][j] > distances[i][k] + distances[k][j]:distances[i][j] = distances[i][k] + distances[k][j]return distancesgraph = {'A': {'B': 1, 'C': 4},'B': {'A': 1, 'C': 2, 'D': 5},'C': {'A': 4, 'B': 2, 'D': 1},'D': {'B': 5, 'C': 1}
}distances = floyd_warshall(graph)
print("Floyd-Warshall Algorithm Output:")
for row in distances:print(row, distances[row])

代码解析

  • floyd_warshall()函数实现了Floyd算法。
  • distances存储每对顶点之间的最短距离。

Floyd-Warshall Algorithm Output:
A {'A': 0, 'B': 1, 'C': 3, 'D': 4}
B {'A': 1, 'B': 0, 'C': 2, 'D': 3}
C {'A': 3, 'B': 2, 'C': 0, 'D': 1}
D {'A': 4, 'B': 3, 'C': 1, 'D': 0} 

4.最小生成树问题

最小生成树问题是指在一个连通图中,找到一棵包含所有顶点且边权值之和最小的树。常见的算法有 Kruskal 算法和 Prim 算法。

1.Kruskal 算法

Kruskal 算法是一种贪心算法,主要思想是每次选择权值最小的边,并保证不形成圈,直到构建出最小生成树。具体步骤如下:

  1. 将图中的所有边按权值从小到大排序。
  2. 初始化一个空集合,用于存放最小生成树的边。
  3. 从权值最小的边开始,依次选择边,如果选择的边与当前集合中的边不形成圈,则将该边加入集合。
  4. 重复步骤 3,直到集合中包含 n-1 条边,其中 n 是图的顶点数。

Kruskal 算法的时间复杂度为 O(E log E),适用于边数较少的稀疏图。

PPT中的示例可以用以下代码展示Kruskal算法:

class DisjointSet:def __init__(self, vertices):self.parent = {v: v for v in vertices}self.rank = {v: 0 for v in vertices}def find(self, item):if self.parent[item] != item:self.parent[item] = self.find(self.parent[item])return self.parent[item]def union(self, set1, set2):root1 = self.find(set1)root2 = self.find(set2)if root1 != root2:if self.rank[root1] > self.rank[root2]:self.parent[root2] = root1else:self.parent[root1] = root2if self.rank[root1] == self.rank[root2]:self.rank[root2] += 1def kruskal(graph):edges = [(weight, u, v) for u in graph for v, weight in graph[u].items()]edges.sort()ds = DisjointSet(graph.keys())mst = []for edge in edges:weight, u, v = edgeif ds.find(u) != ds.find(v):ds.union(u, v)mst.append((u, v, weight))return mstgraph = {'A': {'B': 1, 'C': 4},'B': {'A': 1, 'C': 2, 'D': 5},'C': {'A': 4, 'B': 2, 'D': 1},'D': {'B': 5, 'C': 1}
}mst = kruskal(graph)
print("Kruskal's Algorithm Output:", mst)

代码解析

  • DisjointSet类用于实现并查集,以检测是否形成环。
  • kruskal()函数实现了Kruskal算法。
  • edges存储图中的所有边并按权值排序。
  • mst存储最小生成树的边。

Kruskal's Algorithm Output: [('A', 'B', 1), ('C', 'D', 1), ('B', 'C', 2)] 

2.Prim 算法

Prim 算法也是一种贪心算法,主要思想是从一个顶点开始,每次选择连接已选顶点集合和未选顶点集合的最小权值边,直至所有顶点都被选中。具体步骤如下:

  1. 初始化一个顶点集合,包括图中的任意一个顶点。
  2. 初始化一个空集合,用于存放最小生成树的边。
  3. 从顶点集合中选择一条连接已选顶点和未选顶点的最小权值边,将该边和边的终点加入集合。
  4. 重复步骤 3,直到所有顶点都被选中。

Prim 算法的时间复杂度为 O(V^2),适用于顶点数较少的稠密图。如果使用优先队列进行优化,时间复杂度可以降到 O(E log V)。

PPT中的示例可以用以下代码展示Prim算法:

import heapqdef prim(graph, start):mst = []visited = {start}edges = [(weight, start, to) for to, weight in graph[start].items()]heapq.heapify(edges)while edges:weight, frm, to = heapq.heappop(edges)if to not in visited:visited.add(to)mst.append((frm, to, weight))for to_next, weight in graph[to].items():if to_next not in visited:heapq.heappush(edges, (weight, to, to_next))return mstgraph = {'A': {'B': 1, 'C': 4},'B': {'A': 1, 'C': 2, 'D': 5},'C': {'A': 4, 'B': 2, 'D': 1},'D': {'B': 5, 'C': 1}
}mst = prim(graph, 'A')
print("Prim's Algorithm Output:", mst)

代码解析

  • prim()函数实现了Prim算法。
  • visited存储已选顶点。
  • edges存储连接已选顶点和未选顶点的边。

Prim's Algorithm Output: [('A', 'B', 1), ('B', 'C', 2), ('C', 'D', 1)] 

5.着色问题

图着色是指将图的顶点涂上不同的颜色,使得相邻顶点颜色不同。图着色问题的目的是使用尽可能少的颜色。图着色在调度问题、地图着色等实际问题中有广泛应用。

PPT中的示例可以用以下代码展示图着色:

import networkx as nx
import matplotlib.pyplot as pltdef greedy_coloring(graph):color_map = {}for node in graph:available_colors = set(range(len(graph)))for neighbor in graph[node]:if neighbor in color_map:available_colors.discard(color_map[neighbor])color_map[node] = min(available_colors)return color_mapgraph = {'A': ['B', 'C'],'B': ['A', 'C', 'D'],'C': ['A', 'B', 'D'],'D': ['B', 'C']
}coloring = greedy_coloring(graph)
print("Graph Coloring Output:", coloring)# 可视化图着色
G_coloring = nx.Graph(graph)
colors = [coloring[node] for node in G_coloring.nodes()]
plt.figure(figsize=(8, 6))
plt.title("Graph Coloring")
nx.draw(G_coloring, with_labels=True, node_color=colors, node_size=2000, cmap=plt.cm.rainbow, edge_color='black', linewidths=1, font_size=15)
plt.show()

代码解析

  • greedy_coloring()函数实现了贪心着色算法。
  • color_map存储每个顶点的颜色。
  • available_colors存储每个顶点可用的颜色。

Graph Coloring Output: {'A': 0, 'B': 1, 'C': 2, 'D': 0} 

 

6.旅行商问题

旅行商问题是指在一组城市中找出一条最短路径,使得旅行商访问每个城市一次并回到起点。这是一个经典的 NP 完全问题,求解方法包括近似算法和启发式算法。

近似算法

由于旅行商问题的复杂性,通常使用近似算法来求解,如贪心算法、动态规划等。贪心算法通过每次选择距离当前城市最近的未访问城市来构建路径,而动态规划通过记忆化搜索来避免重复计算。

PPT中的示例可以用以下代码展示旅行商问题:

import itertoolsdef tsp_brute_force(graph):nodes = list(graph.keys())shortest_path = Nonemin_cost = float('infinity')for perm in itertools.permutations(nodes):cost = 0for i in range(len(perm) - 1):cost += graph[perm[i]][perm[i + 1]]cost += graph[perm[-1]][perm[0]]if cost < min_cost:min_cost = costshortest_path = permreturn shortest_path, min_costgraph = {'A': {'B': 10, 'C': 15, 'D': 20},'B': {'A': 10, 'C': 35, 'D': 25},'C': {'A': 15, 'B': 35, 'D': 30},'D': {'A': 20, 'B': 25, 'C': 30}
}path, cost = tsp_brute_force(graph)
print("TSP Brute Force Output:", path, "with cost", cost)

代码解析

  • itertools.permutations()生成所有可能的路径。
  • tsp_brute_force()函数实现了暴力求解旅行商问题。
  • shortest_path存储最短路径,min_cost存储最小成本。

TSP Brute Force Output: ('A', 'B', 'D', 'C') with cost 80 

7.网络最大流问题

网络最大流问题是指在一个流网络中,找到从源点到汇点的最大流量路径。常见的算法有 Ford-Fulkerson 算法。

Ford-Fulkerson 算法

Ford-Fulkerson 算法通过反复寻找增广路径来增加流量,直到找不到增广路径为止。具体步骤如下:

  1. 初始化流量为 0。
  2. 使用深度优先搜索或广度优先搜索找到一条增广路径。
  3. 更新增广路径上的流量,增加路径上的最小残余容量。
  4. 重复步骤 2 和 3,直到找不到增广路径。

Ford-Fulkerson 算法的时间复杂度为 O(E |f|),其中 E 是边数,|f| 是最大流量的值。

PPT中的示例可以用以下代码展示Ford-Fulkerson算法:

from collections import dequedef bfs(C, F, source, sink):queue = deque([source])paths = {source: []}while queue:u = queue.popleft()for v in C[u]:if C[u][v] - F[u][v] > 0 and v not in paths:paths[v] = paths[u] + [(u, v)]if v == sink:return paths[v]queue.append(v)return Nonedef ford_fulkerson(graph, source, sink):C = {u: {} for u in graph}for u in graph:for v, capacity in graph[u].items():C[u][v] = capacityif v not in C:C[v] = {}C[v][u] = 0F = {u: {v: 0 for v in C[u]} for u in C}max_flow = 0while True:path = bfs(C, F, source, sink)if not path:breakflow = min(C[u][v] - F[u][v] for u, v in path)for u, v in path:F[u][v] += flowF[v][u] -= flowmax_flow += flowreturn max_flowgraph = {'A': {'B': 3, 'C': 3},'B': {'C': 2, 'D': 3},'C': {'D': 2, 'E': 2},'D': {'F': 2},'E': {'D': 1, 'F': 3},'F': {}
}max_flow = ford_fulkerson(graph, 'A', 'F')
print("Ford-Fulkerson Algorithm Output:", max_flow)

代码解析

  • bfs()函数实现广度优先搜索,找到增广路径。
  • ford_fulkerson()函数实现Ford-Fulkerson算法。
  • C存储容量,F存储流量。
  • max_flow存储最大流量。

Ford-Fulkerson Algorithm Output: 4 

8.计划评审方法与关键路径

关键路径法(CPM)用于项目管理中,通过计算项目中各任务的最早开始时间和最晚完成时间,找出影响项目工期的关键路径。关键路径是指项目中耗时最长的路径,决定了项目的最短完成时间。

PPT中的示例可以用以下代码展示关键路径法:

def critical_path_method(tasks):longest_path = []max_duration = 0for task in tasks:if task['duration'] > max_duration:max_duration = task['duration']longest_path = [task['name']]elif task['duration'] == max_duration:longest_path.append(task['name'])return longest_path, max_durationtasks = [{'name': 'A', 'duration': 3},{'name': 'B', 'duration': 2},{'name': 'C', 'duration': 4},{'name': 'D', 'duration': 1},{'name': 'E', 'duration': 3}
]path, duration = critical_path_method(tasks)
print("Critical Path Method Output:", path, "with duration", duration)

代码解析

  • critical_path_method()函数计算关键路径。
  • tasks存储每个任务的名称和持续时间。
  • longest_path存储关键路径,max_duration存储最长持续时间。

Critical Path Method Output: ['C'] with duration 4 

9.钢管订购和运输

钢管订购和运输问题涉及从多个供应点向需求点运输钢管,要求最小化运输和铺设费用。具体步骤包括:

  1. 构建运费矩阵,计算从各个供应点到各个需求点的运输费用。
  2. 构建数学规划模型,设定目标函数为总费用最小化。
  3. 使用优化算法求解模型,确定最佳的订购和运输方案。

PPT中的示例可以用以下代码展示钢管订购和运输问题:

from scipy.optimize import linprogc = [20, 30, 10, 40, 30, 20, 10, 20, 10]  # 费用系数
A_eq = [[1, 1, 0, 1, 0, 0, 0, 0, 0],[0, 0, 1, 0, 1, 1, 0, 0, 0],[0, 0, 0, 0, 0, 0, 1, 1, 1]
]  # 约束条件
b_eq = [200, 150, 100]  # 需求
bounds = [(0, float('inf'))] * len(c)  # 变量边界res = linprog(c, A_eq=A_eq, b_eq=b_eq, bounds=bounds, method='highs')
print("Optimal value:", res.fun)
print("Optimal solution:", res.x)

代码解析

  • linprog()函数求解线性规划问题。
  • c表示费用系数,A_eq表示约束条件,b_eq表示需求,bounds表示变量边界。
  • res.fun返回最优值,res.x返回最优解。

Optimal value: 6500.0
Optimal solution: [200.   0. 150.   0.   0.   0. 100.   0.   0.] 

总结

图与网络模型的基本概念、矩阵表示、最短路径、最小生成树、着色问题、旅行商问题、网络最大流问题及关键路径法等主题,结合PPT内容和Python代码实例,深入解析了每个主题的核心算法和应用场景,提供了可视化代码和图形展示,以便更好地理解和应用这些重要的图论算法。

相关文章:

【数学建模】——前沿图与网络模型:新时代算法解析与应用

目录 1.图与网络的基本概念 1. 无向图和有向图 2. 简单图、完全图、赋权图 3. 顶点的度 4. 子图与图的连通性 2.图的矩阵表示 1. 关联矩阵 2. 邻接矩阵 3.最短路问题 1.Dijkstra 算法 2.Floyd 算法 4.最小生成树问题 1.Kruskal 算法 2.Prim 算法 5.着色问题 6.…...

视频分帧【截取图片】(YOLO目标检测【生成数据集】)

高效率制作数据集【按这个流程走&#xff0c;速度很顶】 本次制作&#xff0c;1059张图片【马路上流动车辆】 几乎就是全自动了&#xff0c;只要视频拍得好&#xff0c;YOLO辅助制作数据集就效率极高 视频中的图片抽取&#xff1a; 【由于视频内存过大&#xff0c;遇到报错执行…...

Redis7(二)Redis持久化双雄

持久化之RDB RDB的持久化方式是在指定时间间隔&#xff0c;执行数据集的时间点快照。也就是在指定的时间间隔将内存中的数据集快照写入磁盘&#xff0c;也就是Snapshot内存快照&#xff0c;它恢复时再将硬盘快照文件直接读回到内存里面。 RDB保存的是dump.rdb文件。 自动触发…...

发布支持TS的npm包

你现在有这么一个包&#xff0c;已经将他发布在npm上了&#xff0c;周下载量也还比较可观。美中不足的就是&#xff0c;这个包之前使用js写的&#xff0c;现在你想增加TS类型&#xff0c;提升用户使用体验&#xff0c;那么你现在可以做以下几个步骤 1.在你的包的根目录下创建一…...

计算机视觉9 全卷积网络

全卷积网络&#xff08;Fully Convolutional Network&#xff0c;简称 FCN&#xff09;在计算机视觉领域具有重要地位。 传统的卷积神经网络&#xff08;CNN&#xff09;在最后的输出层通常使用全连接层来进行分类任务。然而&#xff0c;全连接层会丢失空间信息&#xff0c;使得…...

02.C++入门基础(下)

1.函数重载 C支持在同一作用域中出现同名函数&#xff0c;但是要求这些同名函数的形参不同&#xff0c;可以是参数个数不同或者类型不同。这样C函数调用就表现出了多态行为&#xff0c;使用更灵活。C语言是不支持同一作用域中出现同名函数的。 1、参数类型不同 2、参数个数不同…...

【数据结构】探索排序的奥秘

若有不懂地方&#xff0c;可查阅我之前文章哦&#xff01; 个人主页&#xff1a;小八哥向前冲~_csdn博客 所属专栏&#xff1a;数据结构_专栏 目录 排序的概念 几种排序方法介绍 冒泡排序 选择排序 插入排序 堆排序 向上调整建堆排序 向下调整建堆排序 希尔排序 快速…...

数据结构面试知识点总结3

#来自ウルトラマンティガ&#xff08;迪迦&#xff09; 1 线性表 最基本、最简单、最常用的一种数据结构。一个线性表是 n 个具有相同特性的数据元素的有限序列。 特征&#xff1a;数据元素之间是一对一的逻辑关系。 第一个数据元素没有前驱&#xff0c;称为头结点&#xff1…...

python-爬虫实例(5):将进酒,杯莫停!

目录 前言 将进酒&#xff0c;杯莫停&#xff01; 一、浇给 二、前摇 1.导入selenium库 2.下载浏览器驱动 三、爬虫四步走 1.UA伪装 2.获取url 3.发送请求 4.获取响应数据进行解析并保存 总结 前言 博主身为一个农批&#xff0c;当然要尝试爬取王者荣耀的东西啦。 将进…...

AGI 之 【Hugging Face】 的【从零训练Transformer模型】之二 [ 从零训练一个模型 ] 的简单整理

AGI 之 【Hugging Face】 的【从零训练Transformer模型】之二 [ 从零训练一个模型 ] 的简单整理 目录 AGI 之 【Hugging Face】 的【从零训练Transformer模型】之二 [ 从零训练一个模型 ] 的简单整理 一、简单介绍 二、Transformer 1、模型架构 2、应用场景 3、Hugging …...

十大排序的稳定性和时间复杂度

十大排序算法的稳定性和时间复杂度是数据结构和算法中的重要内容。 以下是对这些算法的稳定性和时间复杂度的详细分析&#xff1a; 稳定性 稳定性指的是排序算法在排序过程中是否能够保持相等元素的原始相对顺序。根据这个定义&#xff0c;我们可以将排序算法分为稳定排序和…...

【系列教程之】1、点亮一个LED灯

1、点亮一个LED灯 作者将狼才鲸创建日期2024-07-23 CSDN教程目录地址&#xff1a;【目录】8051汇编与C语言系列教程本Gitee仓库原始地址&#xff1a;才鲸嵌入式/8051_c51_单片机从汇编到C_从Boot到应用实践教程 本源码包含C语言和汇编工程&#xff0c;能直接在电脑中通过Keil…...

搜维尔科技:Manus Metagloves使用精确的量子跟踪技术捕捉手部每一个细节动作

Manus Metagloves使用精确的量子跟踪技术捕捉手部每一个细节动作 搜维尔科技&#xff1a;Manus Metagloves使用精确的量子跟踪技术捕捉手部每一个细节动作...

机器学习 | 阿里云安全恶意程序检测

目录 一、数据探索1.1 数据说明1.2 训练集数据探索1.2.1 数据特征类型1.2.2 数据分布1.2.3 缺失值1.2.4 异常值1.2.5 标签分布探索 1.3 测试集探索1.3.1 数据信息1.3.2 缺失值1.3.3 数据分布1.3.4 异常值 1.4 数据集联合分析1.4.1 file_id 分析1.4.2 API 分析 二、特征工程与基…...

python打包exe文件-实现记录

1、使用pyinstaller库 安装库&#xff1a; pip install pyinstaller打包命令标注主入库程序&#xff1a; pyinstaller -F.\程序入口文件.py 出现了一个问题就是我在打包运行之后会出现有一些插件没有被打包。 解决问题&#xff1a; 通过添加--hidden-importcomtypes.strea…...

基本的DQL语句-单表查询

一、DQL语言 DQL(Data Query Language 数据查询语言)。用途是查询数据库数据&#xff0c;如SELECT语句。是SQL语句 中最核心、最重要的语句&#xff0c;也是使用频率最高的语句。其中&#xff0c;可以根据表的结构和关系分为单表查询和多 表联查。 注意&#xff1a;所有的查询…...

Vue3 对比 Vue2

相关信息简介2020年9月18日&#xff0c;Vue.js发布3.0版本&#xff0c;代号&#xff1a;One Piece&#xff08;海贼王&#xff09; 2 年多开发, 100位贡献者, 2600次提交, 600次 PR、30个RFC Vue3 支持 vue2 的大多数特性 可以更好的支持 Typescript&#xff0c;提供了完整的…...

2024中国大学生算法设计超级联赛(1)

&#x1f680;欢迎来到本文&#x1f680; &#x1f349;个人简介&#xff1a;陈童学哦&#xff0c;彩笔ACMer一枚。 &#x1f3c0;所属专栏&#xff1a;杭电多校集训 本文用于记录回顾总结解题思路便于加深理解。 &#x1f4e2;&#x1f4e2;&#x1f4e2;传送门 A - 循环位移解…...

offer题目51:数组中的逆序对

题目描述&#xff1a;在数组中的两个数字&#xff0c;如果前面一个数字大于后面的数字&#xff0c;则这两个数字组成一个逆序对。输入一个数组&#xff0c;求出这个数组中的逆序对的总数。例如&#xff0c;在数组{7,5,6,4}中&#xff0c;一共存在5个逆序对&#xff0c;分别是(7…...

45、PHP 实现滑动窗口的最大值

题目&#xff1a; PHP 实现滑动窗口的最大值 描述&#xff1a; 给定一个数组和滑动窗口的大小&#xff0c;找出所有滑动窗口里数值的最大值。 例如&#xff1a; 如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3&#xff0c; 那么一共存在6个滑动窗口&#xff0c; 他们的最大值…...

【计算机视觉】siamfc论文复现实现目标追踪

什么是目标跟踪 使用视频序列第一帧的图像(包括bounding box的位置)&#xff0c;来找出目标出现在后序帧位置的一种方法。 什么是孪生网络结构 孪生网络结构其思想是将一个训练样本(已知类别)和一个测试样本(未知类别)输入到两个CNN(这两个CNN往往是权值共享的)中&#xff0…...

数学建模学习(111):改进遗传算法(引入模拟退火、轮盘赌和网格搜索)求解JSP问题

文章目录 一、车间调度问题1.1目前处理方法1.2简单案例 二、基于改进遗传算法求解车间调度2.1车间调度背景介绍2.2遗传算法介绍2.2.1基本流程2.2.2遗传算法的基本操作和公式2.2.3遗传算法的优势2.2.4遗传算法的不足 2.3讲解本文思路及代码2.4算法执行结果&#xff1a; 三、本文…...

Golang | Leetcode Golang题解之第241题为运算表达式设计优先级

题目&#xff1a; 题解&#xff1a; const addition, subtraction, multiplication -1, -2, -3func diffWaysToCompute(expression string) []int {ops : []int{}for i, n : 0, len(expression); i < n; {if unicode.IsDigit(rune(expression[i])) {x : 0for ; i < n &…...

Unity客户端接入原生Google支付

Unity客户端接入原生Google支付 1. Google后台配置2. 开始接入Java部分C#部分Lua部分 3. 导出工程打包测试参考踩坑注意 1. Google后台配置 找到内部测试&#xff08;这个测试轨道过审最快&#xff09;&#xff0c;打包上传&#xff0c;这个包不需要接入支付&#xff0c;如果已…...

Spring Cloud之五大组件

Spring Cloud 是一系列框架的有序集合&#xff0c;为开发者提供了快速构建分布式系统的工具。这些组件可以帮助开发者做服务发现&#xff0c;配置管理&#xff0c;负载均衡&#xff0c;断路器&#xff0c;智能路由&#xff0c;微代理&#xff0c;控制总线等。以下是 Spring Cl…...

在 CentOS 7 上安装 Docker 并安装和部署 .NET Core 3.1

1. 安装 Docker 步骤 1.1&#xff1a;更新包索引并安装依赖包 先安装yum的扩展&#xff0c;yum-utils提供了一些额外的工具&#xff0c;这些工具可以执行比基本yum命令更复杂的任务 sudo yum install -y yum-utils sudo yum update -y #更新系统上已安装的所有软件包到最新…...

redis的学习(一):下载安装启动连接

简介 redis的下载&#xff0c;安装&#xff0c;启动&#xff0c;连接使用 nosql nosql&#xff0c;即非关系型数据库&#xff0c;和传统的关系型数据库的对比&#xff1a; sqlnosql数据结构结构化非结构化数据关联关联的非关联的查询方式sql查询非sql查询事务特性acidbase存…...

前端设计模式面试题汇总

面试题 1. 简述对网站重构的理解&#xff1f; 参考回答&#xff1a; 网站重构&#xff1a;在不改变外部行为的前提下&#xff0c;简化结构、添加可读性&#xff0c;而在网站前端保持一致的行为。也就是说是在不改变UI的情况下&#xff0c;对网站进行优化&#xff0c; 在扩展的…...

linux(CentOS、Ubuntu)安装python3.12.2环境

1.下载官网Python安装包 wget https://www.python.org/ftp/python/3.12.2/Python-3.12.2.tar.xz 1.1解压 tar -xf Python-3.12.2.tar.xz 解压完后切换到Python-3.12.2文件夹(这里根据自己解压的文件夹路径) cd /usr/packages/Python-3.12.2/ 1.2升级软件包管理器 CentOS系…...

CSS 中border-radius 属性

border-radius 属性在 CSS 中用于创建圆角边框。它可以接受一到四个值&#xff0c;这些值可以是长度值&#xff08;如像素 px、em 等&#xff09;或百分比&#xff08;%&#xff09;。当提供四个值时&#xff0c;它们分别对应于边框的左上角、右上角、右下角和左下角的圆角半径…...

【大数据专题】数据仓库

1. 简述数据仓库架构 &#xff1f; 数据仓库的核心功能从源系统抽取数据&#xff0c;通过清洗、转换、标准化&#xff0c;将数据加载到BI平台&#xff0c;进而满足业 务用户的数据分析和决策支持。 数据仓库架构包含三个部分&#xff1a;数据架构、应用程序架构、底层设施 1&…...

go关于string与[]byte再学深一点

目标&#xff1a;充分理解string与[]bytes零拷贝转换的实现 先回顾下string与[]byte的基本知识 1. string与[]byte的数据结构 reflect包中关于字符串的数据结构 // StringHeader is the runtime representation of a string.type StringHeader struct {Data uintptrLen int} …...

Qt 实战(7)元对象系统 | 7.4、属性系统:深度解析与应用

文章目录 一、属性系统&#xff1a;深度解析与应用1、定义属性2、属性系统的作用3、属性系统工作原理&#xff08;1&#xff09;Q_PROPERTY宏&#xff08;2&#xff09;moc 的作用&#xff08;3&#xff09;属性在元对象中的注册 4、获取与设置属性4.1、QObject::property()与Q…...

Docker核心技术:容器技术要解决哪些问题

云原生学习路线导航页&#xff08;持续更新中&#xff09; 本文是 Docker核心技术 系列文章&#xff1a;容器技术要解决哪些问题&#xff0c;其他文章快捷链接如下&#xff1a; 应用架构演进容器技术要解决哪些问题&#xff08;本文&#xff09;Docker的基本使用Docker是如何实…...

sklearn中的增量学习:特征提取的艺术

sklearn中的增量学习&#xff1a;特征提取的艺术 在机器学习领域&#xff0c;特征提取是构建有效模型的关键步骤。然而&#xff0c;并非所有数据集都适合一次性加载到内存中进行处理&#xff0c;尤其是在处理大规模数据集时。Scikit-learn&#xff08;sklearn&#xff09;提供…...

PostgreSQL 中如何处理数据的唯一性约束?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01;&#x1f4da;领书&#xff1a;PostgreSQL 入门到精通.pdf 文章目录 PostgreSQL 中如何处理数据的唯一性约束&#xff1f;一、什么是唯一性约束二、为什么要设置唯一性约束…...

VAE论文阅读

在网上看到的VAE解释&#xff0c;发现有两种版本&#xff1a; 按照原来论文中的公式纯数学推导&#xff0c;一般都是了解生成问题的人写的&#xff0c;对小白很不友好。按照实操版本的&#xff0c;非常简单易懂&#xff0c;比如苏神的。但是却忽略了论文中的公式推导&#xff…...

【数据分享】2013-2022年我国省市县三级的逐月SO2数据(excel\shp格式\免费获取)

空气质量数据是在我们日常研究中经常使用的数据&#xff01;之前我们给大家分享了2000——2022年的省市县三级的逐月PM2.5数据和2013-2022年的省市县三级的逐月CO数据&#xff08;均可查看之前的文章获悉详情&#xff09;&#xff01; 本次我们分享的是我国2013——2022年的省…...

【Jmeter】记录一次Jmeter实战测试

Jmeter实战 1、需求2、实现2.1、新建线程组2.2、导入参数2.3、新建HTTP请求2.4、添加监听器2.5、结果 1、需求 查询某个接口在高并发场景下的响应时间(loadtime)&#xff0c;需求需要响应在50ms以内&#xff0c;接下来用Jmeter测试一下 Jmeter安装见文章《Jemeter安装教程&am…...

volatile,最轻量的同步机制

目录 一、volatile 二、如何使用&#xff1f; 三、volatile关键字能代替synchronized关键字吗&#xff1f; 四、总结&#xff1a; 还是老样子&#xff0c;先来看一段代码&#xff1a; 我们先由我们自己的常规思路分析一下代码&#xff1a;子线程中&#xff0c;一直循环&…...

在Linux、Windows和macOS上释放IP地址并重新获取新IP地址的方法

文章目录 LinuxWindowsmacOS 在Linux、Windows和macOS上释放IP地址并重新获取新IP地址的方法各有不同。以下是针对每种操作系统的详细步骤&#xff1a; Linux 使用DHCP客户端&#xff1a;大多数Linux发行版都使用DHCP&#xff08;动态主机配置协议&#xff09;来自动获取IP地址…...

Mamba-yolo|结合Mamba注意力机制的视觉检测

一、本文介绍 PDF地址&#xff1a;https://arxiv.org/pdf/2405.16605v1 代码地址&#xff1a;GitHub - LeapLabTHU/MLLA: Official repository of MLLA Demystify Mamba in Vision: A Linear AttentionPerspective一文中引入Baseline Mamba&#xff0c;指明Mamba在处理各种高…...

语音识别标记语言(SSML):自动标识中文多音字

好的&#xff0c;以下是完整的实现代码&#xff0c;包括导入库、分词、获取拼音和生成 SSML 标记的全过程&#xff1a; import thulac from pypinyin import pinyin, Style# 初始化 THULAC thu1 thulac.thulac(seg_onlyTrue)# 测试文本 text "银行行长正在走行。"…...

排序算法与复杂度介绍

1. 排序算法 1.1 排序算法介绍 排序也成排序算法&#xff08;Sort Algorithm&#xff09;&#xff0c;排序是将一组数据&#xff0c;依照指定的顺序进行排序的过程 1.2 排序的分类 1、内部排序&#xff1a; 指将需要处理的所有数据都加载到**内部存储器&#xff08;内存&am…...

Kafka介绍及Go操作kafka详解

文章目录 Kafka介绍及Go操作kafka详解项目背景解决方案面临的问题业界方案ELKELK方案的问题日志收集系统架构设计架构设计组件介绍将学到的技能消息队列的通信模型点对点模式 queue发布/订阅 topicKafka介绍Kafka的架构图工作流程选择partition的原则ACK应答机制Topic和数据日志…...

DAY05 CSS

文章目录 1 CSS选择器(Selectors)8. 后代(包含)选择器9. 直接子代选择器10. 兄弟选择器11. 相邻兄弟选择器12. 属性选择器 2 伪元素3 CSS样式优先级1. 相同选择器不同样式2. 相同选择器相同样式3. 继承现象4. 选择器不同权值的计算 4 CSS中的值和单位1. 颜色表示法2. 尺寸表示法…...

HTTPS 的加密过程 详解

HTTP 由于是明文传输&#xff0c;所以安全上存在以下三个风险&#xff1a; 窃听风险&#xff0c;比如通信链路上可以获取通信内容。篡改风险&#xff0c;比如通信内容被篡改。冒充风险&#xff0c;比如冒充网站。 HTTPS 在 HTTP 与 TCP 层之间加入了 SSL/TLS 协议&#xff0c…...

spring整合mybatis,junit纯注解开发(包括连接druid报错的所有解决方法)

目录 Spring整合mybatis开发步骤 第一步&#xff1a;创建我们的数据表 第二步&#xff1a;编写对应的实体类 第三步&#xff1a;在pom.xml中导入我们所需要的坐标 spring所依赖的坐标 mybatis所依赖的坐标 druid数据源坐标 数据库驱动依赖 第四步&#xff1a;编写SpringC…...

ClusterIP、NodePort、LoadBalancer 和 ExternalName

Service 定义 在 Kubernetes 中&#xff0c;由于Pod 是有生命周期的&#xff0c;如果 Pod 重启它的 IP 可能会发生变化以及升级的时候会重建 Pod&#xff0c;我们需要 Service 服务去动态的关联这些 Pod 的 IP 和端口&#xff0c;从而使我们前端用户访问不受后端变更的干扰。 …...

【Day1415】Bean管理、SpringBoot 原理、总结、Maven 高级

0 SpringBoot 配置优先级 从上到下 虽然 springboot 支持多种格式配置文件&#xff0c;但是在项目开发时&#xff0c;推荐统一使用一种格式的配置 &#xff08;yml是主流&#xff09; 1 Bean管理 1.1 从 IOC 容器中获取 Bean 1.2 Bean 作品域 可以通过注解 Scope("proto…...