题目
有 n 个网络节点,标记为 1 到 n。
给你一个列表 times,表示信号经过 有向 边的传递时间。 times[i] = (ui, vi, wi),其中 ui 是源节点,vi 是目标节点, wi 是一个信号从源节点传递到目标节点的时间。
现在,从某个节点 K 发出一个信号。需要多久才能使所有节点都收到信号?如果不能使所有节点收到信号,返回 -1 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/network-delay-time
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
代码
class Solution {
public int networkDelayTime(int[][] times, int n, int k) {
// 节点编号是从 1 开始的,所以要一个大小为 n + 1 的邻接表
List<int[]>[] gragh=new LinkedList[n+1];
for (int i = 1; i <=n ; i++) {
gragh[i]=new LinkedList<>();//实例化
}
//构造图
for (int[] edge: times
) {
int from=edge[0];
int to =edge[1];
int weight=edge[2];
// from -> List<(to, weight)>
// 邻接表存储图结构,同时存储权重信息
gragh[from].add(new int[]{to,weight});
}
// 启动 dijkstra 算法计算以节点 k 为起点到其他节点的最短路径
int[] distTo=dijkstra(k,gragh);
// 找到最长的那一条最短路径
int ans=0;
for (int i = 1; i <distTo.length ; i++) {
if (distTo[i]==Integer.MAX_VALUE){
return -1;//因为有些结点无法达到
}
ans =Math.max(ans,distTo[i]);
}
return ans;
}
// 输入一个起点 start,计算从 start 到其他节点的最短距离
int[] dijkstra(int start, List<int[]>[] graph){
// 定义:distTo[i] 的值就是起点 start 到达节点 i 的最短路径权重
int[] distTo =new int[graph.length];
Arrays.fill(distTo,Integer.MAX_VALUE);//赋值无穷大
// base case,start 到 start 的最短距离就是 0
distTo[start]=0;
// 优先级队列,distFromStart 较小的排在前面
PriorityQueue<State> pq = new PriorityQueue<>(new Comparator<State>() {
@Override
public int compare(State o1, State o2) {
return o1.distFromStart-o2.distFromStart;
}
});
// 从起点 start 开始进行 BFS
pq.offer(new State(start,0));
while (!pq.isEmpty()){
State curState= pq.poll();//获取当前结点信息
int curId = curState.id;
int curdist = curState.distFromStart;//获取当前结点距离起点距离
if (curdist>distTo[curId]){
continue;// 已经有一条更短的路径到达 curNode 节点了
}
// 将 curNode 的相邻节点装入队列
for (int[] neighbor: graph[curId]
) {
int nextNodeId = neighbor[0];//取出邻结点id
int distToNext=distTo[curId]+neighbor[1];//经过cur结点到邻结点这条路径的总长
// 更新 dp table
if (distTo[nextNodeId]>distToNext){
distTo[nextNodeId]=distToNext;
pq.offer(new State(nextNodeId,distToNext));
}
}
}
return distTo;
}
class State{
int id; // 图节点的 id
int distFromStart;// 从 start 节点到当前节点的距离
State(int id,int distFromStart){
this.id=id;
this.distFromStart=distFromStart;
}
}
}
要点
- 本题是单源寻找最短路径问题,使用DIJKSTRA 算法
- 在迪杰斯特拉的基础上,加入最小堆,使得每次选择都是最小的权重,减少时间复杂度
- 对于结点的状态,我们声名一个State类来表示,使得思路更加清晰
- 有些题需要自己建表,对建表操作需要熟悉