参考:
各种最短路算法时间分析参考:http://blog.csdn.net/zxy_snow/article/details/6270468
带权最短路算法分析:https://www.renfei.org/blog/weighted-shortest-path.html
本题题意:算出起点到所有点的最短路总距离,注意本题有重边
例如:1 3 5
1 3 2
那么只能取最短的边
本题代码图的储存方式皆使用静态邻接表,n代表点数,m代表边数:
...
本题中所有算法都有一个dis[n]的数组,下标表示点的编号,数组表示起点到其他每个点的距离。
1.Bellman-Ford
时间复杂度:O(VE),效率一般
适用范围:(很广)允许存在负权边,能够判断图中是否存在从源点可到达的负权环路
主要思想是使用n-1次循环,每次循环将m条边遍历,若可以通过这条边(假设为u到v)
将源点到v的距离,缩短到源点到u再通过这条边到v的距离,更新dis[v]。
核心代码:(本题没使用静态邻接表只用了结构数组记录边的信息)
....
代码用时:155ms
2. SPFA(Bellman-Ford 队列优化)
图解:http://blog.csdn.net/qq_25605637/article/details/50858414
时间复杂度:最坏也是O(kE),k为一较小常量。效率很高
适用范围:(较广),允许存在负权边,但不允许负权环路
代码复杂程度:较易,需队列
主要思想是使用队列去掉bellman的一些不必要判断,采用了一个vis数组标记进入队列的元素。如果这条边(u到v)可以更新dis值,而且v没被标记,将v加入队列,标记v。但本题可能由于代码使用数据结构的不同并没有达到优化效果
核心代码:
代码用时:166ms
3.Dijkstra
适用范围:(一般)不允许存在负权边适用范围:(一般)不允许存在负权边
这个算法复杂度取决于"取最小"(Extract-min)操作使用的算法
Extract-min操作 时间复杂度 代码复杂程度
顺序检测所有点决定最小值 O(V^2) 一般
主要思想 采用n次循环将边进行松弛,每次循环选择dis数组中距离最短的并且未被标记的点松弛,然后对以这点为起点的所有边松弛dis数组,标记该点。
4. Dijkstra(优先队列优化)
适用范围:(一般)不允许存在负权边
这个算法复杂度取决于"取最小"(Extract-min)操作使用的算法
使用Binary-Heap(优先队列) O((V+E)lgV) 较复杂
主要思想是使用优先队列优化每次寻找最短边的操作,其实就是把查找的复杂度降到Ologn?,因为优先队列的数据结构是堆。
需要构建一个结构作为队列元素和重载一个比较函数,还需要运用初始化列表,这部分写法比较难理解,暂且当做模板使用。
队列元素:
代码用时:159ms