关于单源最短路的建图方式
1.四种单源最短路算法
-
Dijkstra
设计思想:dijkstra算法本质上算是贪心的思想,每次在剩余节点中找到离起点最近的节点放到队列中,并用来更新剩下的节点的距离,再将它标记上表示已经找到到它的最短路径,以后不用更新它了。
分为朴素版与堆优化版本
朴素版:- 适用场景:稀疏图且不存在负环。
- 时间复杂度:O(n^2)。
堆优化版本:
- 适用场景:稠密图且不存在负环。
- 时间复杂度:O(nm)。
-
bellman-ford
设计思想:该算法能够保证每更新一次都能确定一个节点的最短路,但与dijkstra不同的是,并不知道是那个节点的最短路被确定了,只是知道比上次多确定一个,这样进行n-1次更新后所有节点的最短路都确定了(源点的距离本来就是确定的)。
适用场景:适用于存在负环的图。
时间复杂度:O(mn)。 -
spfa
设计思想:是对bellman-ford算法的队列优化。所以spfa的做法就是把每次更新了的点放到队列中记录下来。
时间复杂度:一般情况下:O(n);最坏情况下:O(nm),即退化为bellman-ford算法。 -
Floyd
设计思想: Floyd算法是一个经典的动态规划算法。
适用场景:是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包。
时间复杂度:O(n^3)。
总结:在无负环时,一般选用堆优化版本Dijkstra算法求最短路;存在负环时,适用spfa算法求最短路;求多源最短路时,适用Floyd算法求最短路。
2.单源最短路的建图方式:
在单源最短路问题中,所用算法离不开上述四种。而问题的关键在于将题意进行转换,再利用上述算法求解最短路。
以下是几种在做题过程中碰到的建图方式:
- 方式1:传信问题:
- 问题描述:每个信使收到信件后,将信件传递给与他相连的所有信使。问:所有信使都收到信件所需的最少时间。
- 问题解决:由于不知道终点是哪一个信使,所以在数据范围较小的情况下,可以适用Floyd算法,再求出由信使1到其他信使所需的最大时间。
而在数据范围较大的情况下,可以使用堆优化版本的Dijkstra算法,其总时间复杂度为O(n^2log(m))
- 方式2:求最长距离
- 问题解决:可以使用堆优化版本的Dijkstra算法,不过需要使用最大堆。
- 方式3:求最小换乘次数
- 问题描述:有m条巴士线路。问从A到B最少需要换乘几次。
- 问题解决:将一条巴士线路上各个城市之间的距离设置为1,这样就可以转换成为最小路径问题
- 方式4:聘礼问题(多种选择问题)
- 问题描述:国王需要x1元聘金或y1元+z1物品或y2元+z2物品;而其他物品的主人需要xn元或yn元+yn物品;问最少需要花费多少钱。
- 问题解决:需要建立一个虚拟源点,用来表示所连接结点,直接购买所需的费用。问题转化为从虚拟源点到国王结点所需的最小费用。