4 Graph
Dijkstra算法
Dijkstra 算法
Dijkstra(/ˈdikstrɑ/或/ˈdɛikstrɑ/)算法由荷兰计算机科学家 E. W. Dijkstra 于 1956 年发现,1959 年公开发表。是一种求解 非负权图 上单源最短路径的算法。
过程
将结点分成两个集合:已确定最短路长度的点集(记为 集合)的和未确定最短路长度的点集(记为 集合)。一开始所有的点都属于 集合。
初始化 ,其他点的 均为 。
然后重复这些操作:
- 从 集合中,选取一个最短路长度最小的结点,移到 集合中。
- 对那些刚刚被加入 集合的结点的所有出边执行松弛操作。
直到 集合为空,算法结束。

时间复杂度
朴素的实现方法为每次 2 操作执行完毕后,直接在 集合中暴力寻找最短路长度最小的结点。2 操作总时间复杂度为 ,1 操作总时间复杂度为 ,全过程的时间复杂度为 。
可以用堆来优化这一过程:每成功松弛一条边 ,就将 插入堆中(如果 已经在堆中,直接执行 Decrease-key),1 操作直接取堆顶结点即可。共计 次 Decrease-key, 次 pop,选择不同堆可以取到不同的复杂度,参考 堆 页面。堆优化能做到的最优复杂度为 ,能做到这一复杂度的有斐波那契堆等。
特别地,可以使用优先队列维护,此时无法执行 Decrease-key 操作,但可以通过每次松弛时重新插入该结点,且弹出时检查该结点是否已被松弛过,若是则跳过,复杂度 ,优点是实现较简单。
这里的堆也可以用线段树来实现,复杂度为 ,在一些特殊的非递归线段树实现下,该做法常数比堆更小。并且线段树支持的操作更多,在一些特殊图问题上只能用线段树来维护。
在稀疏图中,,堆优化的 Dijkstra 算法具有较大的效率优势;而在稠密图中,,这时候使用朴素实现更优。
实现
这里同时给出 的暴力做法实现和 的优先队列做法实现。
朴素实现
优先队列实现
例题:
Status
Problem
Tags