Q:有 N 个网络节点,标记为 1 到 N。
给定一个列表 times,表示信号经过有向边的传递时间。 times[i] = (u, v, w),其中 u 是源节点,v 是目标节点, w 是一个信号从源节点传递到目标节点的时间。
现在,我们向当前的节点 K 发送了一个信号。需要多久才能使所有节点都收到信号?如果不能使所有节点收到信号,返回 -1。
注意:
N 的范围在 [1, 100] 之间。
K 的范围在 [1, N] 之间。
times 的长度在 [1, 6000] 之间。
所有的边 times[i] = (u, v, w) 都有 1 <= u, v <= N 且 0 <= w <= 100。
A:
1.Dijkstra(迪杰斯特拉)算法
public static int networkDelayTime(int[][] times, int N, int K) {
//创建邻接表,存放各个点到各个点的距离
int[][] graph = new int[N + 1][N + 1];
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++)
graph[i][j] = -1;
}
//遍历times填充邻接表
for (int[] time : times) {
graph[time[0]][time[1]] = time[2];
}
//存放K到各个点的最短路径,最大的为结果
int[] distence = new int[N + 1];
Arrays.fill(distence, -1);
//初始化K到各个节点的距离
for (int i = 1; i <= N; i++) {
distence[i] = graph[K][i];
}
//自己到自己为0
distence[K] = 0;
//判断是否找到K到达该点最短路径
boolean[] visited = new boolean[N + 1];
Arrays.fill(visited, false);
visited[K] = true;
//遍历除K本身外所有N-1个结点,遍历N-1次
for (int i = 1; i <= N - 1; i++) {
int minDis = Integer.MAX_VALUE;
int minIndex = 1;
//遍历所有节点,找到离K最近的
for (int j = 1; j <= N; j++) {
if (!visited[j] && distence[j] != -1 && distence[j] < minDis) {
minDis = distence[j];
minIndex = j;
}
}
//标记最近距离节点被找到
visited[minIndex] = true;
//根据刚刚找到的最近节点,更新与其他节点的距离
for (int j = 1; j <= N; j++) {
//已更新的结点可以到当前节点
if (graph[minIndex][j] != -1) {
if (distence[j] != -1)
//和之前路径的最小值
distence[j] = Math.min(distence[j], distence[minIndex] + graph[minIndex][j]);
else
//该节点第一次访问,直接放入
distence[j] = distence[minIndex] + graph[minIndex][j];
}
}
}
int maxDis = 0;
//遍历最大值,如果有节点未被访问,返回-1
for (int i = 1; i <= N; i++) {
if (distence[i] == -1) {
return -1;
}
maxDis = Math.max(maxDis, distence[i]);
}
return maxDis;
}
2.Floyd(弗洛伊德)算法
public static int networkDelayTime(int[][] times, int N, int K) {
int[][] graph = new int[N + 1][N + 1];
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
graph[i][j] = i == j ? 0 : -1;
}
}
for (int[] time : times) {
graph[time[0]][time[1]] = time[2];
}
//遍历所有节点,用k做松弛
for (int k = 1; k <= N; k++) {
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
//用k松弛i到j的最短路径
if (graph[i][k] != -1 && graph[k][j] != -1) {
if (graph[i][j] != -1) {
graph[i][j] = Math.min(graph[i][j], graph[i][k] + graph[k][j]);
} else {
graph[i][j] = graph[i][k] + graph[k][j];
}
}
}
}
}
int maxDis = 0;
//遍历K到所有节点的最短路径的最大值
for (int i = 1; i <= N; i++) {
if (graph[K][i] == -1) {
return -1;
}
maxDis = Math.max(maxDis, graph[K][i]);
}
return maxDis;
}