LC743.网络延迟时间 (微信公众号@宫水三叶的刷题日记)
- 三叶大佬总结的太好了,先搬过来再慢慢理解;比较好理解的建图方式为邻接矩阵。
class Solution {
int N = 110, M = 6010;
// 邻接矩阵数组:w[a][b] = c 代表从 a 到 b 有权重为 c 的边
int[][] w = new int[N][N];
int INF = 0x3f3f3f3f;
int n , k;
public int networkDelayTime(int[][] times, int _n, int _k) {
n = _n; k = _k;
// 初始化邻接矩阵
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
w[i][j] = w[j][i] = i == j ? 0 : INF;
}
}
// 存图
for (int[] t : times) {
int u = t[0], v = t[1], c = t[2];
w[u][v] = c;
}
// 最短路
floyd();
// 遍历答案
int ans = 0;
for (int i =1; i <= n; i++) {
ans = Math.max(ans, w[k][i]);
}
return ans >= INF ? -1 : ans;
}
void floyd() {
// floyd 基本流程为三层循环:
// 枚举中转点 - 枚举起点 - 枚举终点 - 松弛操作
for (int p = 1; p <= n; p++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
w[i][j] = Math.min(w[i][j], w[i][p] + w[p][j]);
}
}
}
}
}
class Solution {
int N = 110, M = 6010;
// 邻接矩阵数组:w[a][b] = c 代表从 a 到 b 有权重为 c 的边
int[][] w = new int[N][N];
// dist[x] = y 代表从「源点/起点」到 x 的最短距离为 y
int[] dist = new int[N];
// 记录哪些点已经被更新过
boolean[] vis = new boolean[N];
int INF = 0x3f3f3f3f;
int n, k;
public int networkDelayTime(int[][] times, int _n, int _k) {
n = _n; k = _k;
// 初始化邻接矩阵
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
w[i][j] = w[j][i] = i == j? 0 : INF;
}
}
// 存图
for (int[] t : times) {
int u = t[0], v = t[1], c = t[2];
w[u][v] = c;
}
// 最短路
dijkstra();
// 遍历答案
int ans = 0;
for (int i = 1; i <= n; i++) {
ans = Math.max(ans, dist[i]);
}
return ans >= INF ? -1 : ans;
}
private void dijkstra() {
// 起始先将所有的点标记为「未更新」和「距离为正无穷」
Arrays.fill(vis, false);
Arrays.fill(dist, INF);
// 只有起点最短距离为 0
dist[k] = 0;
// 迭代 n 次
for (int p = 1; p <= n; p++) {
// 每次找到「最短距离最小」且「未被更新」的点 t
int t = -1;
for (int i = 1; i <= n; i++) {
if (!vis[i] && (t == -1 || dist[i] < dist[t])) t = i;
}
// 标记点 t 为已更新
vis[t] = true;
// 用点 t 的「最小距离」更新其他点
for (int i = 1; i <= n; i++) {
dist[i] = Math.min(dist[i], dist[t] + w[t][i]);
}
}
}
}
Tip:
- Dijkstra算法:计算从一个点到其余各顶点的最短路径(各边权重必须为正数);
- Floyed算法:计算任意两点之间的最短路径。