在计算最短路径时,Dijkstra
算法和 Bellman-Ford
算法都可以包含环,但是时间复杂度都较高。而有向无环图中,使用拓扑顺序放松边,能非常高效解决单点路径问题。
概念
加权有向无环图最短路径算法:
- 能够在线性时间内解决单点路径问题
- 能够处理负权重的边
- 能够解决相关问题,例如找到最长的路径
其特点是:无环,权重可正可负,但是不能包含环。
算法定义
首先将 distTo[s]
初始化为 0,其他 distTo[]
元素初始化为无穷大,然后一个一个地按照拓扑顺序放松所有顶点。
按照拓扑排序放松所有顶点,能在和
E+V
成正比的时间内解决无环加权有向图的单点路径问题。
动画演示
算法解析
double[] distTo
数组
记录起点到当前顶点的,最短路径估计长度。DirectedEdge[] edgeTo
数组
记录起点到当前顶点最短路径上,最后一条边。也就是说前驱顶点到当前顶点的边。
1 | public class AcyclicSP { |
小结
- 权重
边的权重可正可负,有向图不能包含环。 - 边的放松顺序
按照顶点的拓扑顺序,放松所有的边;且所有的边只会被放松一次。 - 时间复杂度
V
个顶点,E
条边的有向无环图,拓扑排序时间复杂度为O(E+V)
;而根据拓扑顺序放松所有的边为O(E)
;所以总的时间复杂度为O(E+V)
。
最短路径算法对比
Dijkstra
算法
- 特点:支持环,仅能处理权重全为正的有向图
- 时间复杂度为
O(ElogV)
- 边的放松顺序
小根堆取出距离起点距离最近的顶点,依次放松该顶点指向邻接点的边;且每条边只会被放松一次。
Bellman-Ford
算法
- 特点:支持环,权重正或负都能处理,但有向图中不能存在负权重环(如果存在,最短路径树的计算会被无限循环放松)
- 时间复杂度为
O(EV)
- 边的放松顺序
原始Bellman-Ford
算法:以任意顺序放松边,放松V
轮;SPFA
基于队列改进型算法:当distTo[w]
值发生变化的顶点进入队列,以FIFO
的方式放松该顶点指向邻接点的边。
DAG
有向无环图算法
- 特点:不支持环,权重正或负都能处理
- 时间复杂度为
O(E+V)
- 边的放松顺序
按照顶点的拓扑顺序,放松所有的边;且所有的边只会被放松一次。
支持环:仅仅表示有向图中可以有环存在;但最短路径树中是不可能存在环的(不管是正权重环还是负权重环)。三个算法的主要区别在于边的放松顺序不同。
参考文档
- 《算法:第四版》 第 4 章
- algs4: sp
- visualgo动画-Dynamic Programming