Dijkstra 堆优化版
题目描述
给定一个有向带权图,求从起点到所有其他节点的最短路径长度。图中可能存在重边和自环,边权为正数。
Dijkstra 算法适用于所有边权非负的图。堆优化版本通过优先队列(最小堆)快速取出当前距离最小的未确定节点,将时间复杂度从 O(V²) 优化到 O((V + E)log V)。
解题方法:Dijkstra + 堆优化
算法思路
维护一个距离数组 dist,初始时起点距离为 0,其余为无穷大。用最小堆存储 (距离, 节点),每次取出堆顶距离最小的节点,如果该距离已经大于 dist[u] 则跳过(惰性删除),否则遍历其所有邻边尝试松弛。
松弛成功时将新距离入堆。重复此过程直到堆为空。
代码解析
import heapq
def dijkstra(graph, start):
"""
graph: 邻接表 {u: [(v, w), ...]}
start: 起点
返回: 起点到所有点的最短距离
"""
n = len(graph)
dist = [float('inf')] * n
dist[start] = 0
pq = [(0, start)]
while pq:
d, u = heapq.heappop(pq)
# 如果当前距离大于已记录的最短距离,跳过
if d > dist[u]:
continue
for v, w in graph[u]:
nd = d + w
if nd < dist[v]:
dist[v] = nd
heapq.heappush(pq, (nd, v))
return dist代码要点说明
- dist 数组:记录起点到每个节点的当前最短距离,初始化为无穷大。
- 优先队列 pq:以
(距离, 节点)形式存储,Python 的heapq默认按第一个元素排序。 - 惰性删除:
if d > dist[u]: continue用于跳过已经过期的堆元素。节点可能被多次入堆,但只有距离最小的那次才有效。 - 松弛操作:如果通过 u 到达 v 的距离
d + w比当前记录dist[v]更短,则更新并重新入堆。
复杂度分析
- 时间复杂度:O((V + E)log V),每个节点最多入堆一次,每条边被松弛一次,每次堆操作 O(log V)。
- 空间复杂度:O(V),dist 数组和堆各占用 O(V) 空间。
Dijkstra 堆优化版
https://lincodex.cn/index.php/archives/49/