图计算
1、背景
和朋友聊天的时候无意间被问了这样一个为题(如图所示 ps:这都是一群什么样的朋友老研究这稀奇古怪的玩意)。定睛一看这不就是算法里面的迪杰斯特拉算法吗,14年上大学那会儿C语言写的可利索了。但现在属实不做这个很久了。
好在一直在做python的开发,就试着研究python这门胶水语言是不是也能做这件事,果然啊。
虽然研究的很粗浅但觉得比较有意思就试着写了写(也不知道该叫什么名字,就叫图计算吧)。
2、思路和知识点
1、如何将图存储下来并方便计算
python的networkx库可以将图表示出来,并进行路径加权
import networkx as nx
G = nx.Graph()
G.add_weighted_edges_from([('A', 'B', 5), ('A', 'C', 2))]
输出查看结果更加明显
# 输出图
print(G.edges(data=True))
# 遍历图中所有节点名称
print(G.nodes)
输出结果如下
[('A', 'B', {'weight': 5}), ('A', 'C', {'weight': 2})]
['A', 'B', 'C']
2、计算公路总长
其实就是计算最小生成树了
# 依据图构造最小生成树
T = nx.minimum_spanning_tree(G, weight='weight')
# 计算最小生成树的总权重,即路径总长
total_length = sum(d['weight'] for u, v, d in T.edges(data=True))
3、最佳位置选择
计算各个节点到最远节点的距离(迪杰斯塔拉路径),取其中的最小值,取到最小值的店即为最佳选位点
# node节点到其他节点的迪杰斯塔拉路径组成的dict
distances = dict(nx.single_source_dijkstra_path_length(G, node
, weight='weight'))
3、总体实现
mport networkx as nx
# 创建一个简单的图
G = nx.Graph()
# 添加带权重的边
G.add_weighted_edges_from([('A', 'B', 5), ('A', 'C', 2), ('A', 'E', 2.5), ('A', 'D', 2), ('A', 'F', 4)
, ('B', 'C', 5), ('B', 'G', 4)
, ('C', 'E', 1.8)
, ('D', 'E', 1.5), ('D', 'F', 3)
, ('E', 'G', 1.5)
, ('F', 'G', 6)])
T = nx.minimum_spanning_tree(G, weight='weight')
# 计算最小生成树的总权重,即修建公路的总长
total_length = sum(d['weight'] for u, v, d in T.edges(data=True))
print(f"修建公路的总长至少为: {total_length} 公里")
min_max_distance = float('inf')
# 初始化最小最大距离为无穷大
best_school_location = None
# 初始化最佳中学位置为None
# 遍历所有可能的中学位置(即所有村庄)
for node in G.nodes():
# 找到从当前节点到所有其他节点的最短路径长度
distances = dict(nx.single_source_dijkstra_path_length(G, node, weight='weight'))
# 计算最大距离
max_distance = max(distances.values())
# 如果当前节点的最大距离比之前记录的最小最大距离还小,则更新最小最大距离和最佳位置
if max_distance < min_max_distance:
min_max_distance = max_distance
best_school_location = node
print(f"最佳中学建设地点是: {best_school_location}")
print(f"从该地点到最远村庄的优化路程最短为: {min_max_distance} 公里")
运行结果
修建公路的总长至少为: 13.8 公里
最佳中学建设地点是: A
从该地点到最远村庄的优化路程最短为: 5 公里