一、问题引入
在任意一个简单带权图G=<V, E, W>
及v, u ∈ V
中,求u, v
之间的最短路径及距离的问题,该问题即为最短路径问题。
二、算法讲解
1.1 算法内容
- 令 l1 ← 0, p1 ← λ, lj ← +∞, pj ←λ , j = 2,3,4,…,n, P = {v1}, T = V - {V1}, k ← 1, t ← 1。
(λ: 表示为空) - 对 ∀ vj ∈ T ∧ (vk, vj) ∈ E;
令 l ← min{lj, lk + wkj};
若 l = lk + wij, 则令 lj ← l, pj ← vk。 - 求 li = min{ lj | vj ∈ T };
令 P ← P∪{vi}, T ← T - {vi}, k ← i。 - 令 t ← t + 1;
若 t < n, 则转移至步骤2
继续进行。
1.2 题例讲解
1.2.1 题例引入
Q: 求下图中结点u到结点v的最短路径
1.2.2 解答过程
【STEP-1】
- 对
起点u
进行画圈标号;
(即,表明已经找到了u到u的最短路径。) - 将其他结点用
∞
进行标记;
(即表明暂未找到u到其他结点的最短路径。) - 创建集合S,存储已经标号的顶点。
在集合S中的标号称为永久标号;集合S称为永久标号集。
【STEP-2】
- 找到当前永久标号集中的最后一个结点,即
结点u
; - 找到
结点u
相邻的所有结点,对这些结点使用 “[距离]([源头])” 的方法进行标记;
[距离]([源头]) 标记法:
- 距离:起始结点到当前结点的总距离。
- 源头:当前结点的上一个结点,即当前结点是由哪一个结点引出的。
- 在所有标记的结点中,找到路径最短的结点,并对其进行画圈标号;
(图中:结点a
: 2(u);结点c
: 1(u)。则对结点c
进行画圈标号。) - 将新画圈标号的结点置于永久标号集末尾。
【STEP-3】
- 找到当前永久标号集的最后一个结点,即
结点c
; - 找到
结点c
所有相邻且未被画圈标号的结点,对其进行标记;
(图中:结点c
相邻且未被画圈标号的结点为结点d
,则结点d
: 4(c)) - 在所有标记的结点中,找到路径最短的结点,并对其进行画圈标号;
(图中:结点a
: 2(u);结点d
: 4(c)。则对结点c
进行画圈标号。) - 将新画圈标号的结点置于永久标号集末尾。
【STEP-4】
- 找到当前永久标号集的最后一个结点,即
结点a
; - 找到
结点a
所有相邻且未被画圈标号的结点,对其进行标记;
(图中:结点a
相邻且未被画圈标号的结点为结点b
,结点d
;则结点d
: [4(c),3(a)]min ⇒ 3(a);结点b
: 5(a)。)
若一个结点出现多个标记,则选取总距离最小的标记进行保留,其余标记全部删去即可。
- 在所有标记的结点中,找到路径最短的结点,并对其进行画圈标号;
(图中:结点b
: 5(a);结点d
: 3(a)。则对结点d
进行画圈标号。) - 将新画圈标号的结点置于永久标号集末尾。
【STEP-5】
- 找到当前永久标号集的最后一个结点,即
结点d
; - 找到
结点d
所有相邻且未被画圈标号的结点,对其进行标记;
(结点d
相邻且未被画圈标号的结点为结点v
;则结点v
: 5(b)。)
- 在所有标记的结点中,找到路径最短的结点,并对其进行画圈标号;
(图中:结点v
: 5(b);结点b
: 5(a)。两结点的路径相等,无最短路径结点。且此时,结点v
是整体路径的终点,则直接对结点v
进行画圈标号。) - 将新画圈标号的结点置于永久标号集末尾。
【STEP-6】
- 通过回溯法来确定最短路径。
从
结点v
开始往回找,找到起点结点u
即可终止。
(图中:结点v
的标记为 5(d),即由结点v
找到结点d
;结点d
的标记为 3(a),即由结点d
找到结点a
;结点a
的标记为 2(u),即由结点a
找到结点u
;结束。)
【STEP-7】
即上图的最短路径为:u→a→d→v;
最短路长为:5.
三、实战练习
3.1 练习题目
Q:找出下图中,符合要求的最短路径并求出其路径长度。
(1) v0 → v3
(2) v0 → v4
(3) v0 → v5
3.2 解答过程
解答(1: v0 → v3):
- v0 画圈,S = { v0 }。
- v0 相邻标记,v5: 100(v0); v4: 30(v0); v2: 10(v0);
选择最小:v2;
v2 画圈,S = { v0, v2 }。 - v2 相邻标记,v1: 15(v2); v3: 60(v2);
选择最小:v4。(v1中断,无意义,不考虑)
v4 画圈,S = { v0, v2,v4 }。 - v4 相邻标记,v5: [90(v4), 100(v0)]min ⇒ 90(v4); v3: [50(v4), 60(v2)]min ⇒ 50(v4);
选择最小:v3;
v3 画圈,S = { v0, v2,v4,v3 }。 - 回溯:v3 ← v4 ← v0
- 即 v0到v3的最短路径为:v0 → v4 → v3;
最短路长为:50
解答(2:v0 → v4):
- v0 画圈,S = { v0 }。
- v0 相邻标记,v5: 100(v0); v4: 30(v0); v2: 10(v0);
选择最小:v2;
v2 画圈,S = { v0, v2 }。 - v2 相邻标记,v1: 15(v2); v3: 60(v2);
选择最小:v4。(v1中断,无意义,不考虑)
v4 画圈,S = { v0, v2,v4 }。 - 回溯:v4 ← v0
- 即 v0到v3的最短路径为:v0 → v4;
最短路长为:30
解答(3:v0 → v5):
- v0 画圈,S = { v0 }。
- v0 相邻标记,v5: 100(v0); v4: 30(v0); v2: 10(v0);
选择最小:v2;
v2 画圈,S = { v0, v2 }。 - v2 相邻标记,v1: 15(v2); v3: 60(v2);
选择最小:v4。(v1中断,无意义,不考虑)
v4 画圈,S = { v0, v2,v4 }。 - v4 相邻标记,v5: [90(v4), 100(v0)]min ⇒ 90(v4); v3: [50(v4), 60(v2)]min ⇒ 50(v4);
选择最小:v3;
v3 画圈,S = { v0, v2,v4,v3 }。 - v3 相邻标记,v5: [90(v4), 60(v3)]min ⇒ 60(v3)
选择最小:v5;
v5 画圈,S = { v0, v2,v4,v3, v5 } - 回溯:v5 ← v3 ← v4 ← v0
- 即 v0到v5的最短路径为:v0 → v4 → v3 → v5;
最短路长为:60
在上例中,不难发现:
- 结点为a, b, c, d, e, f, g;
- 若a到g的最短路径为a→b→c→d→e→f→g:
- 则b到f的最短路径为b→c→d→e→f;
- 则a到e的最短路径为a→b→c→d→e;
- …………
- 即在已有最短路径中进行相关截取,也可以获得其他结点间的最短路径。
—— writing by Pan Qifan(潘琦藩) ——