赞
踩
目录
通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算)。 此外,引进两个集合S和U。S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离)。 初始时,S中只有起点s;U中是除s之外的顶点,并且U中顶点的路径是"起点s到该顶点的路径"。然后,从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 然后,再从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 ... 重复该操作,直到遍历完所有顶点。
贪心选择性质: 一个图中的点分为两个集合,一个是V:所有点的集合;另一个是S:表明已经找到最短路径的点,即一个点找到了最短路就加入S,而我们要证的就是加入S的点的最短路都已确定。设d[u]表示u点到源点的当前距离,z[u]表示u到源点的最短路。 假设一个点u是加入S集合中的第一个不满足d[u]=z[u]的点,如果u点到源点s没有路,那么d[u]=z[u]=无穷,就不满足z[u]=d[u]这个条件了,所以可以得出s到u一定有条最短路。我们假设y点是V-S中的一点,y-u不一定存在,也就是说y有可能就是u点,然后假设x是y的紧邻前驱,但s-x也不一定存在,s点有可能为x点,因为x已经加入S了,x又是y的紧邻前驱,所以在松弛时已经计算出d[y]=z[y],(因为图中的s-u是一条最短路了,所以此路上的s-y也是s到y的最短路,否则s-u就不是s到u的最短路了)(根据收敛性质:(此中的字母与本文无关,只是描述收敛性质用到)s-u-v是图G某u点,v点属于V的最短路径,而且在松弛边(u,v)之前的任何时间d[u]=z[u],则在操作后总有d[v]=z[v]),到了这里我们就得出了两个不等式,1.在这条路径中看得出d[u]>=z[u]>=z[y]=d[y],2.在选择u点时,只有d[u]<=d[y]时,才会选到u点加入S,从而得到d[u]=d[y]=z[u]=z[y]。
如果P(i,j)={Vi....Vk..Vs...Vj}是从顶点i到j的最短路径,k和s是这条路径上的一个中间顶点,那么P(k,s)必定是从k到s的最短路径。下面证明该性质的正确性。
假设P(i,j)={Vi....Vk..Vs...Vj}是从顶点i到j的最短路径,则有P(i,j)=P(i,k)+P(k,s)+P(s,j)。而P(k,s)不是从k到s的最短距离,那么必定存在另一条从k到s的最短路径P'(k,s),那么P'(i,j)=P(i,k)+P'(k,s)+P(s,j)<P(i,j)。则与P(i,j)是从i到j的最短路径相矛盾。因此该性质得证。
Dijkstra算法操作步骤: (1) 初始时,S只包含起点s;U包含除s外的其他顶点,且U中顶点的距离为"起点s到该顶点的距离"[例如,U中顶点v的距离为(s,v)的长度,然后s和v不相邻,则v的距离为∞]。 (2) 从U中选出"距离最短的顶点k",并将顶点k加入到S中;同时,从U中移除顶点k。 (3) 更新U中各个顶点到起点s的距离。之所以更新U中顶点的距离,是由于上一步中确定了k是求出最短路径的顶点,从而可以利用k来更新其它顶点的距离;例如,(s,v)的距离可能大于(s,k)+(k,v)的距离。 (4) 重复步骤(2)和(3),直到遍历完所有顶点。
补充:适用于稠密图,代码采用优先队列来替代课本上的数组,采用邻接矩阵,算法的时间复杂度为O((|v|+|e|)log|v|). 不适用于有负边的情况,假如一张图里有一个总长为负数的环,那么Dijkstra算法有可能会沿着这个环一直绕下去。另外,如果一张图里有负数边,但没有总长为负数的环,此时可以用Bellman-Ford算法计算,虽然它比Dijkstra慢了一些。 题解: P3371 【模板】单源最短路径(弱化版) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。