给定一个带权有向图
G
=
(
V
,
E
)
G = (V , E)
G=(V,E),其中每条边的权是非负实数,给定
V
V
V中的一个顶点,称为源
计算从源到所有其他各顶点的最短路径长度
Dijkstra算法
Dijkstra算法是解单源最短路径问题的一个贪心算法
其基本思想是,设置顶点集合
S
S
S,并不断地做贪心选择来扩充这个集合,一个顶点属于集合
S
S
S当且仅当从源到该顶点的最短路径长度已知
初始时,
S
S
S中仅含有源,设
u
u
u是
G
G
G的某一个顶点,把从源到
u
u
u且中间只经过
S
S
S中顶点的路称为从源到
u
u
u的特殊路径,并用数组
d
i
s
t
dist
dist记录当前每个顶点所对应的最短特殊路径长度,用数组
p
a
r
e
n
t
[
i
]
parent[i]
parent[i]记录从源到顶点
i
i
i的最短路径上
i
i
i的前一个顶点
Dijkstra算法每次从
V
−
S
V - S
V−S中取出具有最短特殊路长度的顶点
u
u
u,将
u
u
u添加到
S
S
S中,同时对列表
d
i
s
t
dist
dist和
p
a
r
e
n
t
parent
parent做必要的修改,当
d
i
s
t
[
u
]
+
g
r
a
p
h
[
u
]
[
i
]
<
d
i
s
t
[
i
]
dist[u] + graph[u][i] < dist[i]
dist[u]+graph[u][i]<dist[i]时,置
d
i
s
t
[
i
]
=
d
i
s
t
[
u
]
+
g
r
a
p
h
[
u
]
[
i
]
dist[i] = dist[u] + graph[u][i]
dist[i]=dist[u]+graph[u][i],置
p
a
r
e
n
t
[
i
]
=
u
parent[i] = u
parent[i]=u
一旦
S
S
S包含了所有
V
V
V中顶点,
d
i
s
t
dist
dist就记录了从源到所有其他顶点之间的最短路径长度
Dijkstra算法的正确性
贪心选择性质
Dijkstra算法所做的贪心选择是从
V
−
S
V - S
V−S中选择具有最短特殊路径的顶点
u
u
u,从而确定从源到
u
u
u的最短路径长度
d
i
s
t
[
u
]
dist[u]
dist[u],从源到
u
u
u没有更短的其他路径
事实上,如果存在一条从源到
u
u
u且长度比
d
i
s
t
[
u
]
dist[u]
dist[u]更短的路,设这条路初次走出
S
S
S之外到达的顶点为
x
∈
V
−
S
x \in V - S
x∈V−S,然后徘徊于
S
S
S内外若干次,最后离开
S
S
S到达
u
u
u
在这条路径上,分别记
d
(
v
,
x
)
d(v , x)
d(v,x)、
d
(
x
,
u
)
d(x , u)
d(x,u)和
d
(
v
,
u
)
d(v , u)
d(v,u)为顶点
v
v
v到顶点
x
x
x、顶点
x
x
x到顶点
u
u
u和顶点
v
v
v到顶点
u
u
u的路长,那么
d
i
s
t
[
x
]
≤
d
(
v
,
x
)
dist[x] \leq d(v , x)
dist[x]≤d(v,x),
d
(
v
,
x
)
+
d
(
x
,
u
)
=
d
(
v
,
u
)
<
d
i
s
t
[
u
]
d(v , x) + d(x , u) = d(v , u) < dist[u]
d(v,x)+d(x,u)=d(v,u)<dist[u],利用边权的非负性,可知
d
(
x
,
u
)
≥
0
d(x , u) \geq 0
d(x,u)≥0,从而推得
d
i
s
t
[
x
]
<
d
i
s
t
[
u
]
dist[x] < dist[u]
dist[x]<dist[u],此为矛盾
这就证明了
d
i
s
t
[
u
]
dist[u]
dist[u]是从源到顶点
u
u
u的最短路径长度
最优子结构性质
将添加
u
u
u之前的
S
S
S称为
S
′
S^{'}
S′
当添加了
u
u
u后,可能出现一条到顶点
i
i
i的新的特殊路
如果这条新特殊路是经过
S
′
S^{'}
S′到达顶点
u
u
u,然后从
u
u
u经一条边直接到达顶点
i
i
i,则这种路的最短的长度是
d
i
s
t
[
u
]
+
c
[
u
]
[
i
]
dist[u] + c[u][i]
dist[u]+c[u][i],此时,如果
d
i
s
t
[
u
]
+
c
[
u
]
[
i
]
<
d
i
s
t
[
i
]
dist[u] + c[u][i] < dist[i]
dist[u]+c[u][i]<dist[i],则算法中用
d
i
s
t
[
u
]
+
c
[
u
]
[
i
]
dist[u] + c[u][i]
dist[u]+c[u][i]作为
d
i
s
t
[
i
]
dist[i]
dist[i]的新值
如果这条新特殊路经过
S
′
S^{'}
S′到达
u
u
u后,不是从
u
u
u经一条边直接到达
i
i
i,而是回到
S
′
S^{'}
S′中某个顶点
x
x
x,最后才到达顶点
i
i
i,那么由于
x
x
x在
S
′
S^{'}
S′中,因此
x
x
x比
u
u
u先加入
S
S
S,故从源到
x
x
x的路的长度比从源到
u
u
u,再从
u
u
u到
x
x
x的路的长度小,于是当前
d
i
s
t
[
i
]
dist[i]
dist[i]的值小于这条新特殊路的长度,因此,在算法中不必考虑这种路
由此可知,不论算法中
d
i
s
t
[
u
]
dist[u]
dist[u]的值是否有变化,它总是关于当前顶点集
S
S
S到顶点
u
u
u的最短特殊路径长度