xxx 有向无环图(DAG)中的单源最短路径问题
字数 1094 2025-11-07 12:33:00
xxx 有向无环图(DAG)中的单源最短路径问题
题目描述
给定一个带权有向无环图(DAG)和一个源顶点 \(s\),求从 \(s\) 到图中所有其他顶点的最短路径。边的权值可以是正数、负数或零,但图中不能有环(尤其是负权环)。
解题过程
-
核心思路
在DAG中,可以通过拓扑排序确定顶点的线性顺序,使得所有边都从左指向右。利用这一性质,我们可以按拓扑顺序依次松弛每个顶点的出边,确保在处理一个顶点时,所有指向它的顶点的最短路径已被计算完成。 -
步骤详解
-
步骤1:拓扑排序
使用深度优先搜索(DFS)或Kahn算法(基于入度)生成拓扑序列。例如,对于下图(顶点A为源点):A → B (权重2) A → C (权重1) B → D (权重3) C → D (权重-1) D → E (权重4)拓扑序列可能为:
[A, B, C, D, E]。 -
步骤2:初始化距离
设数组dist[]存储从源点 \(s\) 到各顶点的最短距离:dist[s] = 0(源点到自身距离为0)- 其他顶点初始化为
∞(表示尚未可达)。
-
步骤3:按拓扑顺序松弛出边
遍历拓扑序列中的每个顶点u,对其每条出边(u, v)执行松弛操作:如果 dist[u] + weight(u, v) < dist[v]: 更新 dist[v] = dist[u] + weight(u, v) 记录 v 的前驱节点为 u(用于重构路径)由于按拓扑顺序处理,当处理到
u时,所有指向u的路径已被计算,因此dist[u]已是最终最短距离。
-
-
示例演示
对上述图以A为源点:- 初始化:
dist = [A:0, B:∞, C:∞, D:∞, E:∞] - 处理A:
- 松弛A→B:
dist[B] = 0 + 2 = 2 - 松弛A→C:
dist[C] = 0 + 1 = 1
- 松弛A→B:
- 处理B:
- 松弛B→D:
dist[D] = 2 + 3 = 5
- 松弛B→D:
- 处理C:
- 松弛C→D:
1 + (-1) = 0 < 5,更新dist[D] = 0
- 松弛C→D:
- 处理D:
- 松弛D→E:
dist[E] = 0 + 4 = 4
- 松弛D→E:
- 最终结果:
[A:0, B:2, C:1, D:0, E:4]
- 初始化:
-
为什么有效?
- 无环保证:拓扑排序避免了重复处理顶点(如Bellman-Ford需多次迭代)。
- 负权边兼容:松弛操作不依赖权值正负,但需无环防止负权环导致的无限循环。
- 时间复杂度:拓扑排序 \(O(V+E)\) + 一次遍历松弛 \(O(V+E)\),总复杂度为 \(O(V+E)\),优于Dijkstra(\(O(E+V\log V)\))和Bellman-Ford(\(O(VE)\))。
-
应用场景
- 项目管理中的关键路径分析(含负权边时仍有效)。
- 依赖关系图中的最短任务调度。
总结
通过拓扑排序将DAG转化为线性序列,再按顺序松弛出边,即可高效解决含负权边的单源最短路径问题,且无需担心负权环的干扰。