是否在Floyd-Warshall算法中重新排列外循环,因为大多数内循环会改变算法
以下代码用于 Floyd-Warshall 算法
for (int k = 0; k < n; ++k) {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}
}
}
我建议将代码改写如下
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
for (int k = 0; k < n; ++k) {
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}
}
}
在新代码中,我将原来的外层循环放到了最内层的循环中。我发现新代码很容易理解解决所有对最短路径问题。我的问题是:新代码是否等同于 Floyd-Warshall 算法的原始代码?
回答
不,这通常不起作用。Floyd-Warshall 算法的核心思想是找到经过较小节点子集的最短路径:1..k,然后增加该子集的大小。
在增加该子集的大小之前,必须使节点对的距离适应子集 1..k。
以维基百科上使用的示例图为例:
让我们关注从节点 3 到节点 1 的路径,它的最小权重路径为 2 + -1 + 4 = 5。
让我们运行原始算法和您的变体,看看它是否识别了这个距离:
原始(正确)算法
let d = [
[0, Infinity, -2, Infinity],
[4, 0, 3, Infinity],
[Infinity, Infinity, 0, 2],
[Infinity, -1, Infinity, 0]
];
let n = d.length;
for (let k = 0; k < n; ++k) {
for (let i = 0; i < n; ++i) {
for (let j = 0; j < n; ++j) {
d[i][j] = Math.min(d[i][j], d[i][k] + d[k][j]);
}
}
}
console.log("distance from 3 to 1 = ", d[2][0]); // 5 -- correct
您建议的算法
let d = [
[0, Infinity, -2, Infinity],
[4, 0, 3, Infinity],
[Infinity, Infinity, 0, 2],
[Infinity, -1, Infinity, 0]
];
let n = d.length;
for (let i = 0; i < n; ++i) {
for (let j = 0; j < n; ++j) {
for (let k = 0; k < n; ++k) {
d[i][j] = Math.min(d[i][j], d[i][k] + d[k][j]);
}
}
}
console.log("distance from 3 to 1 = ", d[2][0]); // Infinity -- wrong
THE END
二维码