dijkstra适合用于求图中给定两点间的距离,并具有优良的效率。但是如果在需要得知任意两点间的最短路距离时,每次询问都跑dijkstra显然不是最优策略。
而求任意两点间距离时,我们可以使用 Floyd 算法来求解,该算法存在三重循环:枚举中间点 k 、起点 x 、终点 y :每次使用 x 与 k 和 k 与 y 之间的距离更新 x 与 y 之间的距离。通俗来说,Floyd 算法检查了两个点之间是否能通过走其他点(k)来获得更短的距离。很明显时间复杂度为
O
(
n
3
)
O(n^3)
O(n3)
代码模板(c++)
for(int k = 1; k<=n; k++)
for(int i = 1; i<=n; i++)
for(int j = 1; j<=n; j++)
g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
其中 g[i][j]
代表了从 i 出发走向 j 的最短路径距离,因此,Floyd 更适合用于邻接矩阵的情况。
Floyd 也可以用来求解传递闭包问题
传递闭包问题:假设有三个数字 a、b、c,已知
a
>
b
a > b
a>b 且
b
>
c
b > c
b>c,问 a 与 c 的大小关系。我们可以将其抽象成一个图论问题,
a
>
b
a > b
a>b 那么代表从 b 向 a 有一条单向边,
b
>
c
b > c
b>c 代表从 c 向 b 有一条单向边,那么问题就转化成了从 c 是否能走到 a。同样可以使用 Floyd 解决:
g[b][a] = 1, g[c][b] = 1;
for(int k = 1; k <= n; k ++ )
for(int i = 1; i <= n; i ++ )
for(int j = 1; j <= n; j ++ )
if(g[i][k] && g[k][j]) g[i][j] = 1;
cout << (g[c][a] ? "Yes" : "No") << '\n';