一、图论基本概念
点表示事物,连接两点的线表示关系。
图的数学表达:G (V(G), E(G) )
其中,V指图的顶点集,E指图的边集。
做图网址:https://csacademy.com/app/graph_editor/
无向图权重邻接矩阵
1) 对称矩阵
2)主对角线元素为0
3)表示i到j节点的权重
节点个数 | 1 | 2 | 3 | 4 |
---|---|---|---|---|
1 | 0 | inf | 3 | 3 |
2 | inf | 0 | inf | 5 |
3 | 3 | inf | 0 | 2 |
4 | 3 | 5 | 2 | 0 |
二、DIJKATRA迪杰斯特拉
算法思路:
①两个集合:集合a用来存放已经找到最短路径的点
集合b用来存放还未找到最短路径的点
(P S:一开始,只有源点在集合a中)
(P S:在代码中可以用flag=True/False来表示是否在集合a中)
②dis[n]数组:用来存放源点到各个点的距离
road[n][n]:用来存放m条有向边(eg. road[3][4] 表示点3到点4的距离)
算法实现:
①查找从源点出发的有向线段,录入 dis[i]
②查找 dis 中最小值(在集合b中的点),并把此点(记为pre)加入到集合a中
③查找从 pre 出发的有向线段,比较 dis[i] 和 dis[pre]+road[pre][i] 的大小,更新 dis[i]
④直至 集合b 的点都加入到 集合a 中
局限性:不能处理有负权重的图
三、Bellman Ford贝尔曼福特
适用场景:具有负权重的有向图
与Dij的区别:不再区分为是否已经访问,每循环一次更新所有节点信息。
四、代码实现
def dijkstra(graph,start): #graph表示点线相连权重
distances = {vertex: float('infinity') for vertex in graph}
distances[start] = 0 #源点到自身为0,未连接线段为inf无穷
parent = {vertex: None for vertex in graph}
priority_queue = [(0,start)] # 初始化父亲节点,未访问任何节点所以全部设置为 None
while priority_queue:
# 弹出堆中距离最小的节点
current_distance, current_vertex = heapq.heappop(priority_queue)
# print("距离最小的节点是:",current_distance, current_vertex, "更新后的队列:",priority_queue)
# 如果当前距离已经大于已知的最短距离,则跳过
if current_distance > distances[current_vertex]:
continue
# 更新相邻节点的距离
for neighbor, weight in graph[current_vertex].items():
distance = current_distance + weight
# print("相邻节点的距离:",neighbor,distance)
# 如果找到更短的路径,则更新距离,并将节点加入优先队列
if distance < distances[neighbor]:
distances[neighbor] = distance
parent[neighbor] = current_vertex
heapq.heappush(priority_queue, (distance, neighbor))
# print("加入后的队列:",priority_queue)
return distances, parent
函数返回值:从起始点到每个节点的最短距离,和每个节点对应的父亲节点。