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; } }