如果节点k是路径p上的中间节点,则将路径p分解成p1:i→k和p2:k→j。可得p1是从结点 i到结点 k 的,中间结点全部取自集合 {1,2,3,… k - 1}的一条最短路径(因为 k 是末尾结点)。类似的,p2是从结点 k到结点 j的,中间结点全部取自集合 {1,2,3,… k - 1}的一条最短路径。
classGraph { constructor(n, edges) { this.INF = Math.floor(Number.MAX_SAFE_INTEGER / 3); // 防止更新最短路时加法溢出 this.d = newArray(n).fill(null).map(() =>newArray(n).fill(this.INF)); // 邻接矩阵(初始化为无穷大,表示 i 到 j 没有边) for (let i = 0; i < n; ++i) { this.d[i][i] = 0; } for (const e of edges) { this.d[e[0]][e[1]] = e[2]; // 添加一条边(输入保证没有重边和自环) } for (let k = 0; k < n; ++k) { for (let i = 0; i < n; ++i) { for (let j = 0; j < n; ++j) { this.d[i][j] = Math.min(this.d[i][j], this.d[i][k] + this.d[k][j]); } } } }
addEdge(e) { const x = e[0], y = e[1], w = e[2], n = this.d.length; if (w >= this.d[x][y]) { // 无需更新 return; } for (let i = 0; i < n; ++i) { for (let j = 0; j < n; ++j) { this.d[i][j] = Math.min(this.d[i][j], this.d[i][x] + w + this.d[y][j]); } } }
shortestPath(start, end) { const ans = this.d[start][end]; return ans < this.INF / 3 ? ans : -1; } }