📅  最后修改于: 2023-12-03 15:12:44.721000             🧑  作者: Mango
给定一个无向图 $G=(V,E)$ 和一个起点 $s$,请实现一个函数 shortest_path(u: int, v: int, G: Dict[int, List[int]], s: int) -> Tuple[List[int], float]
,用于计算从点 $u$ 到点 $v$ 的最短路径。其中 $G$ 为邻接表表示,键值为节点编号,值则为跟该节点直接相连的节点组成的列表。同时,每条边都有一个边权值,每个边权值均为正实数。
函数需要返回一个二元组,第一个元素为从 $u$ 到 $v$ 的路径(以列表形式存储),第二个元素为总路径长度。
G = {
1: [2, 3],
2: [1, 3, 4],
3: [1, 2, 4],
4: [2, 3]
}
s = 1
shortest_path(1, 4, G, s)
输出:
([1, 2, 4], 3.0)
本题属于图论算法的基础题目,可以使用 Dijkstra 算法或 Bellman-Ford 算法求解最短路径。
在本题中,我们使用 Dijkstra 算法。具体思路如下:
dist
,每个元素初始化为正无穷。visited
中。heap
中。heap
中取出当前距离起点最短的节点 $u$,将其加入到已访问节点的集合 visited
中,并更新与其相邻节点的距离。同时,将这些相邻节点加入到堆 heap
中。heap
中没有节点或者当前取出的节点为 $v$。import heapq
from typing import Dict, List, Tuple
def shortest_path(u: int, v: int, G: Dict[int, List[int]], s: int) -> Tuple[List[int], float]:
# 起点的距离赋为 0
dist = {i: float('inf') for i in G}
dist[s] = 0
heap = [(0, s)]
visited = set()
while heap:
d, u = heapq.heappop(heap)
if u == v:
break
if u in visited:
continue
visited.add(u)
for w in G[u]:
if w in visited:
continue
if dist[w] > dist[u] + 1:
dist[w] = dist[u] + 1
heapq.heappush(heap, (dist[w], w))
if dist[v] == float('inf'):
return [], 0.0
path = [v]
while v != u:
for w in G[v]:
if dist[w] < dist[v]:
path.append(w)
v = w
break
return path[::-1], dist[path[-1]]
本算法的时间复杂度为 $O(|E|\log|V|)$,其中 $|V|$ 为节点数目,$|E|$ 为边数目。该算法在最糟糕的情况下需要遍历所有的边和节点。空间复杂度为 $O(|V|)$,用于存储距离数组 dist
。