无向图的单源最短路径问题(Dijkstra算法)
字数 1088 2025-11-30 13:56:58
无向图的单源最短路径问题(Dijkstra算法)
题目描述
给定一个无向图,图中每条边有一个非负权值(即距离或成本),并指定一个起点(源点)。要求找出从源点到图中所有其他顶点的最短路径长度。如果存在无法到达的顶点,则其最短路径长度为无穷大。
解题过程
Dijkstra算法是解决非负权图单源最短路径问题的经典算法。其核心思想是贪心策略:每次从未确定最短路径的顶点中选取距离源点最近的顶点,并更新其邻居的距离。以下是详细步骤:
-
初始化
- 创建一个数组
dist,用于记录源点到每个顶点的当前最短距离估计。初始时,dist[源点] = 0,其他顶点设为无穷大(表示尚未到达)。 - 创建一个优先队列(最小堆),用于高效获取当前距离最小的顶点。初始时将源点及其距离
0入队。 - 创建一个集合(或布尔数组)
visited,标记顶点是否已确定最短路径。
- 创建一个数组
-
主循环
当优先队列不为空时,重复以下步骤:- 提取最小距离顶点:从队列中取出当前距离源点最近的顶点
u,及其距离d。 - 跳过已处理顶点:如果
u已被标记为visited,说明其最短路径已确定,直接跳过。 - 标记为已处理:将
u标记为visited,此时dist[u]即为最终最短距离。 - 松弛操作:遍历
u的所有邻居顶点v,检查是否存在更短路径:
若dist[u] + weight(u, v) < dist[v],则更新dist[v] = dist[u] + weight(u, v),并将v及其新距离加入优先队列。
- 提取最小距离顶点:从队列中取出当前距离源点最近的顶点
-
终止条件
- 当所有顶点均被标记为
visited(或优先队列为空)时,算法结束。此时dist数组存储的就是源点到所有顶点的最短距离。
- 当所有顶点均被标记为
关键点说明
- 贪心正确性:由于边权非负,每次选择最小距离顶点时,其当前距离不可能再被其他路径刷新。
- 时间复杂度:使用二叉堆实现的优先队列,时间为 O((V+E) log V),其中 V 为顶点数,E 为边数。
- 适用限制:不适用于包含负权边的图(可能产生错误结果)。
示例
假设无向图包含顶点 {A, B, C},边权为 A-B:2, A-C:4, B-C:1,源点为 A:
- 初始化:dist[A]=0, dist[B]=∞, dist[C]=∞。
- 处理 A:更新 B=2, C=4。
- 处理 B(当前最小):通过 B 更新 C 为 2+1=3(优于原来的 4)。
- 处理 C:无需更新。
- 结果:dist[A]=0, dist[B]=2, dist[C]=3。