有 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
Dijkstra基本思想
通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算)。
此外,引进两个集合S和U。S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离)。
初始时,S中只有起点s;U中是除s之外的顶点,并且U中顶点的路径是"起点s到该顶点的路径"。然后,从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 然后,再从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 ... 重复该操作,直到遍历完所有顶点。
解题思路
使用Dijkstra的最短路径算法
- 先构建图的邻接矩阵,使用权重填充有向边对应的元素
- 使用最小堆,小根堆中的元素为{起点出发到当前节点的距离,当前节点的标号},以有向边的权值进行比较
- 每次选择最小边,且没到遍历过的节点进行操作,将相邻的节点入队
- 直到所有节点都遍历完一次为止,如果不能遍历完所有的节点则返回-1
代码
class Solution {
public int networkDelayTime(int[][] times, int n, int k) {
int[][] g=new int[n+1][n+1];
int[] dist=new int[n+1];
Arrays.fill(dist,-1);
for(int i=0;i<=n;i++)
Arrays.fill(g[i],-1);
for(int[] time:times)
g[time[0]][time[1]]=time[2];
PriorityQueue<int[]> pq=new PriorityQueue<>((o1,o2) -> o1[0]-o2[0]);
pq.add(new int[]{0,k});
while(!pq.isEmpty())
{
int[] cur=pq.poll();
if(dist[cur[1]]!=-1) continue;
dist[cur[1]]=cur[0];
for(int i=1;i<=n;i++)
if(g[cur[1]][i]!=-1)
{
pq.add(new int[]{cur[0]+g[cur[1]][i],i});
}
}
int cnt=0,max=0;
for(int i=1;i<=n;i++)
{
if(dist[i]==-1)
return -1;
max=Math.max(max,dist[i]);
}
return max;
}
}