题目
有 n 个网络节点,标记为 1 到 n。
给你一个列表 times,表示信号经过 有向 边的传递时间。 times[i] = (ui, vi, wi),其中 ui 是源节点,vi 是目标节点, wi 是一个信号从源节点传递到目标节点的时间。
现在,从某个节点 K 发出一个信号。需要多久才能使所有节点都收到信号?如果不能使所有节点收到信号,返回 -1 。
示例 1:
输入:times = [[2,1,1],[2,3,1],[3,4,1]], n = 4, k = 2
输出:2
示例 2:
输入:times = [[1,2,1]], n = 2, k = 1
输出:1
示例 3:
输入:times = [[1,2,1]], n = 2, k = 2
输出:-1
提示:
- 1 <= k <= n <= 100
- 1 <= times.length <= 6000
- times[i].length == 3
- 1 <= ui, vi <= n
- ui != vi
- 0 <= wi <= 100
- 所有 (ui, vi) 对都 互不相同(即,不含重复边)
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/network-delay-time
Dijkstra解法
解题思路
-
题目实际是求节点K到其他所有点中最远的距离,所以首先求出节点K到其他所有点的最短路,然后取最大值即可
-
Dijkstra算法:
-
核心思路就是贪心,从所有未确定最短路的点中,找到距离K点最近的点x
int x = -1; for (int j = 0; j < n; j++) { if (!used[j] && (x == -1 || dist[j] < dist[x])) x = j; }
-
通过点x更新所有点距离K点的最短距离。
for (int j = 0; j < n; j++) { dist[j] = Math.min(dist[j], dist[x] + map[x][j]); }
-
将点x标记为已经确定最短路。
used[x] = true;
-
重复123步骤,直到所有点标记为已确定最短路,循环结束
-
代码
class Solution {
public int networkDelayTime(int[][] times, int n, int k) {
final int INF = Integer.MAX_VALUE / 2;
if (times.length == 0) return - 1;
// 邻接矩阵存储边信息
int[][] map = new int[n][n];
for (int i = 0; i < n; i++) {
Arrays.fill(map[i], INF);
}
for (int[] time : times) {
int i = time[0] - 1;
int j = time[1] - 1;
map[i][j] = time[2];
}
// 使用dijsktra计算k点到其他所有点的最短距离,并返回为int[]
int[] dist = dijkstra(map, n, k);
// 找到距离最远的点
int res = Arrays.stream(dist).max().getAsInt();
return res == INF ? -1 : res;
}
public int[] dijkstra(int[][] map, int n, int k) {
final int INF = Integer.MAX_VALUE / 2;
// 从源点到某点的距离数组
int[] dist = new int[n];
Arrays.fill(dist, INF);
// 由于从 k 开始,所以该点距离设为 0,也即源点
dist[k - 1] = 0;
// 节点是否被更新数组
boolean[] used = new boolean[n];
for (int i = 0; i < n; i++) {
// 在还未确定最短路的点中,寻找距离最小的点
int cur = -1;
for (int j = 0; j < n; j++) {
if (!used[j] && (cur == -1 || dist[j] < dist[cur])) cur = j;
}
// 用该点更新所有其他点的距离
used[cur] = true;
for (int j = 0; j < n; j++) {
dist[j] = Math.min(dist[j], dist[cur] + map[cur][j]);
}
}
return dist;
}
}