Shortest Path

Published: by Creative Commons Licence

本文讨论的是带权有向图,并称路径上第一个顶点为源点(Source),最后一个顶点为终点(Destination)。

下面是两种最常见的最短路径问题:

  1. 从某个源点到其余各顶点的最短路径 - Dijkstra算法
  2. 每一对顶点之间的最短路径 - Floyd算法

Dijkstra算法

Dijkstra算法适用于求从某个源点到其余各顶点的最短路径的问题。

Dijkstra算法步骤

Dijkstra算法步骤

例子

Dijkstra算法例子

详细解释

Dijkstra例子解释

Dijkstra算法是基于贪心策略的。

不论是使用邻接矩阵表示,还是带权的邻接表表示,Dijkstra算法的时间复杂度都是O(|V|^2)

另外,边上带有负权值时,Dijkstra算法并不适用。

Floyd算法

求所有顶点之间的路径的最短路径问题描述如下:已知一个各边权值均大于0的带权有向图,对任意两个顶点vi!=vj,要求求出vi和vj之间的最短路径和最短路径长度。

Floyd算法的基本思想

Floyd算法基本思想

Floyd算法的算法描述

算法描述1 算法描述2

例子以及算法执行过程

例子以及算法执行过程

技巧说明

  • A的上标i表示当前以vi作为中间顶点。
  • 对角线数值恒为0;
  • 如果以vi为中间顶点,则第i行和第i列的数值都不变;
  • 剩余位置的数值为min(原本的数值, 当前位置投影到第i行对应位置数值和当前投影到第i列对应位置数值之和)

Floyd算法的时间复杂度为O(|V|^3)

但是由于Floyd算法的代码很紧凑,且不包含其他复杂的数据结构,因此隐含的常数系数很小,即使对于中等规模的输入来说,它仍然是相当有效的。

算法的适用范围

  • Floyd算法允许图中有带负权的边,但不允许有包含带负权值的边组成回路
  • Floyd算法同样适用于带权无向图,因为带权无向图可视为权值相同往返二重边的有向图。

该问题的其他解法

单源最短路径来解决每对顶点之间的最短路径问题。轮流将每个顶点作为源点,并且在所有边权值均非负,运行一次Dijkstra算法,其时间复杂度为O(|V|^2) * |V| = O(|V|^3)