Dijkstra最短路径算法

Dijkstra最短路径算法

首先描述一下问题:给定一个有向图G和源点v,求v0到G中某个顶点u的最短路径。限定各边上的权值大于或等于0。

算法的基本思想很简单:所有的顶点,按照它到源点v的距离,客观上存在一个从小到大的顺序,我们只要按照这个顺序找下去,总有一步会找到目标顶点u,而此时的距离就是u到源点v的距离。

想法简单,但关键是怎么按照“客观存在的大小顺序”计算各点到源点v的距离呢?我们先简单思考一下,按照距离v的远近顺序,v一定是排第一的,然后呢,排第二的一定是和v直接相连的点吧,否则总有一个点介于排第二的点和v之间,而它到v的距离肯定也比第二到v的距离近,那这个第二就有些名副其实了。比较麻烦的是,排第三的点在哪里?利用递归的想法就会发现,排第三的点应该从那些和v直接相连,或者和第二名直接相连的点中去寻找,否则第三名就会名副其实了。总结一下,需要找第n个点时,只需要在那些和前n-1个点直接相连的点里面找就行了。

Dijkstra算法的具体实现方法为:

1.设置两个顶点的集合T和S:

a) S中存放已找到最短路径的顶点,初始时,集合S中只有一个顶点,即源点v0;

b) T中存放当前还未找到最短路径的顶点;

2.在T集合中选取当前长度最短的一条最短路径(v0,…,vk),从而将vk加入到顶点集合S中,并修改源点v0到T中各顶点的最短路径长度;重复这一步骤,直到所有的顶点都加入到集合S中,算法就结束了。

下面给个用Dijkstra计算最短路径的例子

1)首先求出长度最短的一条最短路径,即顶点0到顶点2的最短路径,其长度为5,其实就是顶点0到其他各顶点的直接路径中最短的路径(v0→v2)。

2)顶点2的最短路径求出来以后,顶点0到其他各顶点的最短路径长度有可能要改变。例如从顶点0到顶点1的最短路径长度由∞缩短为20,从顶点0到顶点5的最短路径长度也由∞缩短为12。这样长度次短的最短路径长度就是在还未确定最终的最短路径长度的顶点中选择最小的,即顶点0到顶点5的最短路径长度,为12,其路径为(v0→v2→v5)。

3)顶点5的最短路径求出来以后,顶点0到其他各顶点的最短路径长度有可能要改变。例如从顶点0到顶点3的最短路径长度由30缩短为22,从顶点0到顶点4的最短路径长度也由∞缩短为30。这样长度第三短的最短路径长度就是在还未确定最终的最短路径长度的顶点中选择最小的,即顶点0到顶点1的最短路径长度,为20,其路径为(v0→v2→v1)。

4)此后再依次确定顶点0到顶点3的最短路径(v0→v2→v5→v3),其长度为22;以及顶点0到顶点4的最短路径(v0→v2→v1→v4),其长度为28。



看完就懂了!一篇搞定图论最短路径问题

最常见的问题——单源最短路

传说中如雷贯耳的“单源最短路”应该是做题中最常见到的问题了。也即,指定源点,求它到其余各个结点的最短路

比如给出这张图,假设把1号结点作为源点。

还是用数组dis来存1号到其余各点的初始路程:

既然是求最短路径,那先选一个离1号最近的结点,也就是2号结点。这时候,dis[2]=1 就固定了,它就是1到2的最短路径。这是为啥?因为目前离1号最近的是2号,且这个图的所有边都是正数,那就不可能能通过第三个结点中转使得距离进一步缩短了。因为从1号出发已经找不到哪条路比直接到达2号更短了。

选好了2号结点,现在看看2号的出边,有2->3和2->4。先讨论通过2->3这条边能否让1号到3号的路程变短,也即比较dis[3]和dis[2]+e[2][3]的大小。发现是可以的,于是dis[3]从12变为新的更短路10。同理,通过2->4也条边也更新下dis[4]。

松弛完毕后dis数组变为:

接下来,继续在剩下的 3 4 5 6 结点中选一个离1号最近的结点。发现当前是4号离1号最近,于是dis[4]确定了下来,然后继续对4的所有出边看看能不能做松弛。

balabala,这样一直做下去直到已经没有“剩下的”结点,算法结束。

这就是Dijkstra算法,整个算法的基本步骤是:

  1. 所有结点分为两部分:已确定最短路的结点集合P、未知最短路的结点集合Q。最开始,P中只有源点这一个结点。(可用一个book数组来维护是否在P中)
  2. 在Q中选取一个离源点最近的结点u(dis[u]最小)加入集合P。然后考察u的所有出边,做松弛操作。
  3. 重复第二步,直到集合Q为空。最终dis数组的值就是源点到所有顶点的最短路。

Dijkstra是一种基于贪心策略的算法。每次新扩展一个路径最短的点,更新与它相邻的所有点。当所有边权为正时,由于不会存在一个路程更短的没扩展过的点,所以这个点的路程就确定下来了,这保证了算法的正确性。

但也正因为这样,这个算法不能处理负权边,因为扩展到负权边的时候会产生更短的路径,有可能破坏了已经更新的点路程不会改变的性质。

于是,Bellman-Ford算法华丽丽的出场啦。

 
原文地址:https://www.cnblogs.com/chucklu/p/14744945.html