Dijkstra算法求单源最短路
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dijkstra算法求单源最短路相关的知识,希望对你有一定的参考价值。
参考技术Adijkstra算法用于求解单源最短路问题,只能求解正权图,图中有负边求出来的结果会有问题。
算法的思想就是先确定一个起点(源点),然后寻找这个点到其他所有点的距离最小值,找到一条距离最短的线路。
第一次查询这条路径一定是只有这两个点的,确定了这个点,就标记一下,说明这个已经是最短的了,接下来这个点就不参与比较了。
标记过后就把这个点延伸出去的边处理下,因为还要去选从起点到其他点的最短距离,所以要借助这个点去更新一下其他点的最小距离。因为第一次查询时只存储了与源点直连的点,有的点没有与源点直接连接,现在就可以借助这个确定的点进行间接连接。然后把其他直接连接的距离处理更新下。然后重复进行找距离源点最近的点,然后进行更新标记。
每一次循环会标记一个点,所以循环n次就能把n个点的图处理完毕。
第一行包含整数 n 和 m 。
接下来 m 行每行包含三个整数 x , y , z ,表示存在一条从点 x 到点 y 的有向边,边长为 z 。
求解从点1到点n 的最短路径。
堆优化版要用邻接表(链式前向星)进行存图,如果是稠密图推荐用邻接矩阵存图用朴素做法。
堆优化版在算法竞赛中比较适用,可以大幅提高运行效率。
优化思路:
因为每次循环都要去找下一个距离源点最近的的点,但是朴素做法每次都要把所有点都比较判断下,如果每次当有新的距离更新了,就把这个距离装到堆中,那么就不用再去一个个比较了,直接把堆顶元素取出就行了。
dist数组存储的是从源点到其他n个点的距离,每次找的也是这个距离,一次更新一个点,更新完毕就是起点到n个点之间的最短路。
Bellman-ford 单源最短路径算法
参考技术A 参考: Bellman-Ford 单源最短路径算法
Bellman-ford 算法
Bellman-Ford 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法
对于带权有向图 G = (V, E),Dijkstra 算法要求图 G 中边的权值均为非负,而Bellman-ford能适应一般的情况(即 存在负权边 的情况)。
Bellman-ford 采用动态规划的方法,实现的时间复杂度为 O(V*E),其中 V 为顶点数量,E 为边的数量。
Dijkstra 算法采用贪心算法的方法,普通实现的时间复杂度为 O(V^2)。若使用优先队列则时间复杂度为 O(E + VlogV)。
Bellman-Ford 算法描述:
对u节点到v节点的距离进行的松弛操作,如果到u的距离加上u到v的边小于到v的距离,那么可以缩短距离,更新之。
G:为一个图
w:权重二维数组,反映的是u到v的边的权重。
第一个双重for循环:循环V - 1次,对于每个边,都进行松弛操作
第二个for循环:检查是否有环。因为已经进行了V-1次循环了,理论上不应该可以松弛,但如果还有可以松弛的,说明存在负权环,返回False。
为什么要循环V-1次?
因为最短路径肯定是个简单路径,不可能包含回路,如果包含回路,但回路的权值和为正,也松弛不了,还是可以得到更短的路径。但如果回路的权值是负的,就可以一直松弛,那么肯定没有解。图有n个点,又不能有回路,所以最短路径最多n-1边(可以想象成一条线)。又因为每次循环至少松弛一条边,所以最多n-1次就行了。
一开始,源节点到自己的距离为0,到其他节点的距离为∞。
然后对于源节点的 邻接节点 ,比较从源节点加上边的和与其本身距离的值,若小,则更新。
以此类推,循环V - 1次(节点数减1次)
最后检查是否还可以松弛,如果可以,说明有环
以上是关于Dijkstra算法求单源最短路的主要内容,如果未能解决你的问题,请参考以下文章