最优子结构——最短路径的子路径也是最短路径,动态规划和贪心算法的一个重要指标。
环路 一条最短路径不可能包含环路 1) 环路权重为负,如果有一条环路权重为负,则不存在最短路径 2) 环路权重为零,如果包含该环路,则将该环路去掉即可 3) 环路权重为正,去掉改环路可以得到更短的路径,因此不可能是最短路径
最短路径的表示 对于每个结点v,维持一个前驱结点v.p,可能是另外一个结点或者NIL
松弛操作 对每个结点,维持一个属性v.d,记录从源结点s到结点v的最短路径权重的上界;称v.d为s到v的
最短路径估计。
INITIALIZE-SINGLE-SOURCE(G, s)
//最短路径估计及前驱结点初始化 for each vertex v 属于 G.V v.d = INF v.p = NIL s.d = 0
松弛过程【针对一条边(u, v)】:先测试是否可以对s到v的最短路径进行改善,测试的方法为,将从结点s到结点u的最短路径距离加上u与v之间的边权重,并与当前的s到v的最短路径估计进行比较;如果前者更小,则进行v.d和v.p的更新 RELAX(u, v, w) if v.d > u.d + w(u, v) v.d = u.d + w(u, v) v.p = u
Bellman-Ford算法 一般情况下的单源最短路径问题,边的权重可以为负值 返回一个布尔值,以表明是否存在一个从源结点可以到达的权重为负值的环路 BELLMAN-FORD(G, w, s) INITIALIZE-SINGLE-SOURCE(G, s)
//对各个结点的p和d进行初始化 for i = 1 to |G.V| – 1
//每一个点,对每一条边都需要进行松弛操作 for each edge(u, v) 属于 G.E RELAX(u, v, w) for each edge(u, v) 属于 G.E if v.d > u.d + w(u, v)
//如果不存在权重为负值的环路,则二者是相等的 return FALSE return TRUE
有向无环图中的单源最短路径问题 根据结点的拓扑顺序次序来对带权重的有向无环图G = (V, E)进行边的松弛操作,可以在O(V + E)时间内计算出从单源最短路径问题 DAG-SHORTEST-PATHS(G, w, s) topologically sort the vertices of G
//先对点进行拓扑排序,O(V + E)
INITIALIZE-SINGLE-SOURCE(G, s)
for each vertex u, taken in topologically sorted order
//按拓扑排序对结点进行一遍处理
for each vertex v 属于 G.Adj[u]
RELAX(u, v, w)
Dijkstra算法
要求所有变的权重都为非负值
维持了一组结点集合S,源结点s到这组结点的最短路径已经求出;算法重复从V-S中选择最短路径估计最小的结点u,将u加入到集合S中,然后对所有从u发出的边进行松弛
使用一个最小优先队列Q保存结点集合S,每个结点的关键字为其d值
DIJKSTRA(G, w, s)
INITIALIZE-SINGLE-SOURCE(G, s)
S = 空集
Q = G.V
while Q 不等于 空集
u = EXTRACT-MIN(Q) //第一个被提取的点即源结点
S = S 并上 {u}
for each vertex v 属于 G.Adj[u]
RELAX(u, v, w)