算法设计与分析课程复习笔记12——全点对最短路径
全成对最短路径
输入:有向图G=(V,E), 权函数w,
计算:图中任何点对之间的最短距离
结果表示: n × n矩阵, 元素是对应的点对之间的最短距离δ(u, v)
解决方案:
- 对于每一个顶点, 运行BELLMAN-FORD(单源最短))
计算开销: O(V2E), 甚至O(V4):对于边稠密的图 - 如果不存在负权值边, 可利用Dijkstra’s算法计算单源最短
计算开销:O(VElgV), 甚至O(V3lgV):对于边稠密的图 - 可以设计O(V3)开销的全成对最短路径算法,且不需要特殊的数据结构
最短路径的优化结构
- 最短路径的部分路径必然是最短的
- p是从i到j至多含有m条边的最短路径
if i = j ,w(p) = 0
if i ≠ j , p = i ~(p’)k→j,p’最多有m-1条边,p’也是最短路径
δ(i, j) = δ(i, k) + w k j w_{kj} wkj
递归解
l
i
j
(
m
)
l_{ij}^{(m)}
lij(m):从i到j至多含有m条边的最短路径的权
m=0,
l
i
j
(
0
)
l_{ij}^{(0)}
lij(0)=0,if i =j;
l
i
j
(
0
)
l_{ij}^{(0)}
lij(0)=
∞
\infty
∞,if i ≠j。
m
≥
\geq
≥ 0,
l
i
j
(
m
)
l_{ij}^{(m)}
lij(m) =
m
i
n
1
≤
k
≤
n
{
l
i
k
(
m
−
1
)
+
w
k
j
}
min_{1≤k≤n}\{l_{ik}^{(m-1)}+w_{kj}\}
min1≤k≤n{lik(m−1)+wkj}
计算最短路径
m=1:
l
i
j
(
1
)
l_{ij}^{(1)}
lij(1)=
w
i
j
w_{ij}
wij,
L
(
1
)
L^{(1)}
L(1)=W
给出W = (
w
i
j
w_{ij}
wij), 计算
L
(
1
)
,
L
(
2
)
,
…
,
L
(
n
−
1
)
L^{(1)}, L^{(2)}, …, L^{(n-1)}
L(1),L(2),…,L(n−1)
L
(
n
−
1
)
L^{(n-1)}
L(n−1)包含最短路径
计算过程:给出
L
(
m
−
1
)
L^{(m-1)}
L(m−1)和W,计算
L
(
m
)
L^{(m)}
L(m)
如果没有负权回路, 所有的最短路径至多含有n -1条边, 因此有
δ(i, j) =
l
i
j
(
n
−
1
)
l_{ij}^{(n-1)}
lij(n−1)and
l
i
j
(
n
)
l_{ij}^{(n)}
lij(n),
l
i
j
(
n
+
1
)
l_{ij}^{(n+1)}
lij(n+1)……=
l
i
j
(
n
−
1
)
l_{ij}^{(n-1)}
lij(n−1)
延伸算法
Extend(L,W,n)
create L’, an n*n matrix
for i ← 1 to n
do for j ← 1 to n
do
l
i
j
′
l_{ij}'
lij′ ←
∞
\infty
∞
for k ← 1 to n
do
l
i
j
′
l_{ij}'
lij′ ← min(
l
i
j
′
l_{ij}'
lij′,
l
i
k
l_{ik}
lik+
w
k
j
w_{kj}
wkj)
return L’
运行开销: Θ ( n 3 ) Θ(n^3) Θ(n3)
成对最短路径算法(慢速)
SLOW-ALL-PAIRS-SHORTEST-PATHS(W,n)
L
(
1
)
L^{(1)}
L(1) ← W
for m ← 2 to n-1
do
L
(
m
)
L^{(m)}
L(m) ← Extend(
L
(
m
−
1
)
L^{(m-1)}
L(m−1),W,n)
return
L
(
n
−
1
)
L^{(n-1)}
L(n−1)
运行开销: Θ ( n 4 ) Θ(n^4) Θ(n4)
例如给定W,先计算
L
(
1
)
L^{(1)}
L(1)=W,则
L
(
m
−
1
)
L^{(m-1)}
L(m−1)=
L
(
1
)
L^{(1)}
L(1),接着由
L
(
m
−
1
)
L^{(m-1)}
L(m−1)和W计算
L
(
m
)
L^{(m)}
L(m)=
L
(
2
)
L^{(2)}
L(2),以此类推,直到计算出
L
(
4
)
L^{(4)}
L(4)
改进运行时间
- 不必计算所有 L ( m ) L^{(m)} L(m)
- 如果没有负回路, 则有: L ( m ) L^{(m)} L(m)= L ( n − 1 ) L^{(n-1)} L(n−1) for all m ≥ \geq ≥n-1
- 通过计算以下序列: L ( 1 ) L^{(1)} L(1)=W, L ( 2 ) L^{(2)} L(2)=W2=W*W, L ( 4 ) L^{(4)} L(4)=W4=W2*W2, L ( 8 ) L^{(8)} L(8)=W8=W4*W4
L ( n − 1 ) L^{(n-1)} L(n−1)= W 2 ⌈ l g ( n − 1 ) ⌉ W^{2^{\lceil lg(n-1)\rceil}} W2⌈lg(n−1)⌉
快速算法FASTER-APSP(W, n)
L
(
1
)
L^{(1)}
L(1) ← W
m ← 1
while m < n-1
do
L
(
2
m
)
L^{(2m)}
L(2m) ← Extend(
L
(
m
)
L^{(m)}
L(m),
L
(
m
)
L^{(m)}
L(m),n)
m ← 2m
return
L
(
m
)
L^{(m)}
L(m)
运行开销: Θ ( n 3 l g n ) Θ(n^3lgn) Θ(n3lgn)
Floyd-Warshall 算法
给定:G(V,E),可以存在负权边,但不能存在负权回路。
计算:点对之间的最短距离
最短路径结构
对于任何点对i和j, 考虑所有从i到j的路径, 这些路径的中间节点来自集合{1, 2, …, k}
d
i
j
(
k
)
d_{ij}^{(k)}
dij(k):从i到j的路径的权值, 中间节点来自集合{1, 2, …, k} )
例如:
如果顶点k不是路径p的中间节点,则从i到j的中间节点来自{1, 2, …,k}的最短路径即是从i到j的中间节点来自{1,2, …, k - 1}的最短路径。
如果顶点k是路径p的中间节点,则
p
1
p_1
p1是i到k的最短路径,
p
2
p_2
p2是k到j的最短路径,k不是
p
1
p_1
p1,
p
2
p_2
p2的中间节点,
p
1
p_1
p1和
p
2
p_2
p2是最短路径。
递归解
k=0,
d
i
j
(
k
)
d_{ij}^{(k)}
dij(k)=
w
i
j
w_{ij}
wij
k
≥
\geq
≥ 1,顶点k不是路径p的中间节点,
d
i
j
(
k
)
d_{ij}^{(k)}
dij(k)=
d
i
j
(
k
−
1
)
d_{ij}^{(k-1)}
dij(k−1)
顶点k是路径p的中间节点,
d
i
j
(
k
)
d_{ij}^{(k)}
dij(k)=
d
i
k
(
k
−
1
)
d_{ik}^{(k-1)}
dik(k−1)+
d
k
j
(
k
−
1
)
d_{kj}^{(k-1)}
dkj(k−1)
最终解: D ( n ) D^{(n)} D(n)=( d i j ( n ) d_{ij}^{(n)} dij(n))
FLOYD-WARSHALL(W)
n ← rows[W]
D
(
0
)
D^{(0)}
D(0) ← W
for k ← 1 to n
do for i ← 1 to n
do for j ← 1 to n
do
d
i
j
(
k
)
d_{ij}^{(k)}
dij(k) ← min(
d
i
j
(
k
−
1
)
d_{ij}^{(k-1)}
dij(k−1),
d
i
k
(
k
−
1
)
d_{ik}^{(k-1)}
dik(k−1)+
d
k
j
(
k
−
1
)
d_{kj}^{(k-1)}
dkj(k−1))
return
D
(
n
)
D^{(n)}
D(n)
运行开销:
Θ
(
n
3
)
Θ(n^3)
Θ(n3)
参考:任课教师邱德红教授的课件