Dijkstra 算法
743.网络延迟时间
有向+带环+非负权重图+最短路径 【DijKstra】
将所有节点分成两类:
1)已确定从起点到当前点的最短路长度的节点
2)未确定从起点到当前点的最短路长度的节点(下面简称「未确定节点」和「已确定节点」)。
每次从「未确定节点」中取一个与起点距离最短的点,将它归类为「已确定节点」,并用它「更新」从起点到其他所有「未确定节点」的距离。直到所有点都被归类为「已确定节点」。
用节点 AA「更新」节点 BB 的意思是,用起点到节点 AA 的最短路长度加上从节点 AA 到节点 BB 的边的长度,去比较起点到节点 BB 的最短路长度,如果前者小于后者,就用前者更新后者。这种操作也被叫做「松弛」。
这里暗含的信息是:每次选择「未确定节点」时,起点到它的最短路径的长度可以被确定。
可以这样理解,因为我们已经用了每一个「已确定节点」更新过了当前节点,无需再次更新(因为一个点不能多次到达)。而当前节点已经是所有「未确定节点」中与起点距离最短的点,不可能被其它「未确定节点」更新。所以当前节点可以被归类为「已确定节点」
/**
*根据题意,从节点 KK 发出的信号,到达节点 xx 的时间就是节点 KK 到节点 xx 的最短路的长度。
*因此我们需要求出节点 KK 到其余所有点的最短路,其中的最大值就是答案。
*若存在从 KK 出发无法到达的点,则返回 -1−1。
*下面的代码将节点编号减小了 11,从而使节点编号位于 [0,n-1][0,n−1] 范围。
**/
class Solution {
public int networkDelayTime(int[][] times, int n, int k) {
final int INF = Integer.MAX_VALUE / 2;
int[][] g = new int[n][n];
for (int i = 0; i < n; ++i) {
Arrays.fill(g[i], INF);
}
for (int[] t : times) {
int x = t[0] - 1, y = t[1] - 1;
g[x][y] = t[2];
}
int[] dist = new int[n];
Arrays.fill(dist, INF);
dist[k - 1] = 0;
boolean[] used = new boolean[n];
for (int i = 0; i < n; ++i) {
int x = -1;
for (int y = 0; y < n; ++y) {
if (!used[y] && (x == -1 || dist[y] < dist[x])) {
x = y;
}
}
used[x] = true;
for (int y = 0; y < n; ++y) {
dist[y] = Math.min(dist[y], dist[x] + g[x][y]);
}
}
int ans = Arrays.stream(dist).max().getAsInt();
return ans == INF ? -1 : ans;
}
}