1.问题
(1)用Floyd算法求解下图各个顶点的最短距离。写出Floyd算法的伪代码和给出距离矩阵(顶点之间的最短距离矩阵)。
(2)对于下图使用Dijkstra算法求由顶点a到顶点h的最短路径。
2.解析
(1)
从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比已知的路径更短,如果是就更新它。
把图用邻接矩阵G表示出来,如果从Vi到Vj有路可达,则G[i][j]=d,d表示该路的长度;否则G[i][j]=无穷大。定义一个矩阵D用来记录所插入点的信息,D[i][j]表示从Vi到Vj需要经过的点,初始化D[i][j]=j。把各个顶点插入图中,比较插点后的距离与原来的距离,G[i][j] = min( G[i][j], G[i][k]+G[k][j] ),如果G[i][j]的值变小,则D[i][j]=k。在G中包含有两点之间最短道路的信息,而在D中则包含了最短通路径的信息。
(2)
把顶点集合V分成两组:
① S:已求出的顶点的集合(初始时只含有源点V0)
② V-S=T:尚未确定的顶点集合
将T中顶点按递增的次序加入到S中,保证:
① 从源点V0到S中其他各顶点的长度都不大于从V0到T中任何顶点的最短路径长度
② 每个顶点对应一个距离值
S中顶点:从V0到此顶点的长度
T中顶点:从V0到此顶点的只包括S中顶点作中间顶点的最短路径长度
3.设计
(1)伪代码:
Floyd(W[1…n,1…n])
D←W
for k←1 to n do
for i←1 to n do
for j←1 to n do
D[i,j] ← min{D[i,j],D[i,k]+D[k,j]}
return D
(2)伪代码:
Dijkstra(G,s)
Initialize(Q)
for V中每一个顶点v
dv ← ∞; pv ← null;
Insert(Q,v,dv)
ds ←0; Decrease(Q,s,ds)
VT ← Ø
for i ← 0 to |V| -1 do
u* ← DeleteMin(Q)
VT ← VT ∪ {u*}
for V-VT 中每一个和u*相邻的顶点u do
if du* + w(u*,u) < du
du ← du* + w(u*,u); pu ← u*
Decrease(Q,u,du)
4.分析
(1)时间复杂度:O(n3)
(2)时间复杂度:O(|E| log|V|)
5.源码
(1)Floyd算法:
https://github.com/Hyacincy/-/blob/main/Floyd.cpp
(2)Dijkstra算法:
https://github.com/Hyacincy/-/blob/main/Dijkstra.cpp