算法导论—最短路径

华电北风吹
日期:2016/1/16

最短路径求法包含单源最短路径和所有节点对的最短路径。单源最短路径有Dijkstra算法和Bellman-Ford算法。所有节点对的最短路径求法有基于动态规划的矩阵乘法和Floyd-Warshall算法和针对稀疏图的Johnson算法。

一、松弛操作
松弛操作是基于图中的有向边,通过边的起点对终点的最短路径长度上界进行压缩的一种方法。比如图中存在一条a->b的边,长度为 lab ,a和b到源点S的当前路径距离分别为 sa sb ,若 sa+lab<sb ,那么 sb=sa+lab

二、单源最短路径
1、Bellman-Ford算法
对于图G=(V,E),最短路径的长度肯定小于|V|,因此对所有的边松弛|V|次以后得到的路径肯定是最短路径,这也是Bellman-Ford算法的原理。时间复杂度为 O(VE)

2、Dijkstra算法
Dijkstra算法是跟广度优先搜索比较类似的贪心算法。在给定源节点以后,每次从未找到最短路径的节点中选择与源节点距离最小的节点,把当前路径设置为该节点到源节点的最短路径,并根据当前结点的边表的那些有向边进行松弛操作。直到找到所有节点的最短路径。

三、所有节点对的最短路径
1、动态规划(矩阵乘法)
很显然,最短路径长度不会超过节点数目|V|。因此可以把最短路径长度的最大值当作状态,依次求解每个状态下的所有节点的最短路径。
假设每个状态下的最短路径矩阵用 S1,S2,...,S|V1| 。受矩阵乘法启发,一种可以提高效率的计算顺序是 S1,S2,S4,S8,... 。这样可以将状态的计算个数有 |V1| 较少到 log(|V1|)

2、Floyd-Warshall算法
上一个方法是基于路径长度作为状态进行计算,这样在计算每个状态的最短距离矩阵的每个元素的时候,需要把所有的节点给遍历一遍,以确定当前路径下该节点的最短路径。Floyd-Warshall算法以节点作为状态,这样可以免去上一个方法的对所有节点的遍历过程,而专注于当前结点对最短路径的影响,因此可以将计算复杂度降低一个|V|数量级(如果用了第一个方法的提高效率的技巧,则是降低了一个 log(|V|) 数量级)。

3、针对稀疏图的Johnson算法
John算法通过设置虚拟节点,对节点赋予权重(Bellman-Ford算法),来讲存在负权重的图,构建成一个新的不存在负权重的边的图,然后在稀疏图上运行Dijkstra算法,来计算所有节点对的最短路径。

你可能感兴趣的:(算法导论—最短路径)