《灵珠觉醒:从零到算法金仙的C++修炼》卷三·天劫试炼(45)血海轮回阵 - Floyd-Warshall 多源最短路径
《灵珠觉醒:从零到算法金仙的C++修炼》卷三·天劫试炼(45)血海轮回阵 - Floyd-Warshall 多源最短路径
哪吒在数据修仙界中继续他的修炼之旅。这一次,他来到了一片神秘的血海轮回阵,阵中血液般的液体在沟渠中流动,形成复杂的路径。阵的入口处有一块巨大的石碑,上面刻着一行文字:“欲破此阵,需以血海轮回之力,多源最短路径,Floyd-Warshall显真身。”
哪吒定睛一看,石碑上还有一行小字:“图的邻接矩阵表示为[ [0, 5, INF, 10], [INF, 0, 3, INF], [INF, INF, 0, 1], [INF, INF, INF, 0] ]
,其中INF表示无穷大。所有节点之间的最短路径为:0到1为5,0到2为8,0到3为9,1到2为3,1到3为4,2到3为1。”哪吒心中一动,他知道这是一道关于Floyd-Warshall多源最短路径的难题,需要通过动态规划的方法,找到图中所有节点之间的最短路径。
暴力解法:血海轮回的初次尝试
哪吒心想:“要找到所有节点之间的最短路径,我可以多次运行Dijkstra算法。”他催动血海轮回之力,为每个节点分别运行Dijkstra算法,试图找到所有节点之间的最短路径。
void floydWarshall(vector<vector<int>>& dist) {
int n = dist.size();
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (i == j) continue;
if (dist[i][j] == INT_MAX) continue;
for (int k = 0; k < n; ++k) {
if (dist[i][k] != INT_MAX && dist[k][j] != INT_MAX) {
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
}
}
}
}
}
哪吒成功地找到了所有节点之间的最短路径,但血海轮回的光芒却黯淡了下来。他意识到,这种方法虽然可行,但效率低下,尤其是当图的节点数量很多时,灵力消耗巨大。
C++语法点
在C++中,Floyd-Warshall算法涉及到三维循环和动态规划。以下是一些重要特性:
-
三维循环:
- 外层循环遍历中间节点。
- 中层循环遍历起点节点。
- 内层循环遍历终点节点。
-
动态规划:
- 通过状态转移方程
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])
更新最短路径。
- 通过状态转移方程
高阶优化:动态规划的智慧
哪吒元神中突然浮现金色铭文——「血海轮回阵,Floyd-Warshall显真身」。他意识到,可以通过Floyd-Warshall算法优化多源最短路径的计算过程。
哪吒决定使用Floyd-Warshall算法,通过动态规划的方法,逐步引入中间节点,更新所有节点之间的最短路径。通过这种方式,他成功地找到了所有节点之间的最短路径,而且灵力消耗大幅减少。
void floydWarshall(vector<vector<int>>& dist