例题:743. 网络延迟时间
有 n 个网络节点,标记为 1 到 n。
给你一个列表 times,表示信号经过 有向 边的传递时间。 times[i] = (ui, vi, wi),其中 ui 是源节点,vi 是目标节点, wi 是一个信号从源节点传递到目标节点的时间。
现在,从某个节点 K 发出一个信号。需要多久才能使所有节点都收到信号?如果不能使所有节点收到信号,返回 -1 。
输入:times = [[2,1,1],[2,3,1],[3,4,1]], n = 4, k = 2 输出:2
// 邻接表
class Table{
public int u;
public List<Integer> v = new ArrayList<>();
public List<Integer> w = new ArrayList<>();
Table(int u){
this.u = u;
}
}
// 单个节点
class Node{
public int u;
public int dis;
Node(int u, int dis){
this.u = u;
this.dis = dis;
}
}
class Solution {
Table [] tables; // 邻接表
int [] dis; // 离起点的距离
int [] vis; // 是否访问过
int [] p; // 访问路径
// 初始化
public void init(int n){
tables = new Table[n];
dis = new int[n];
vis = new int [n];
p = new int[n];
for(int i=0;i<n;i++){
tables[i] = new Table(i);
}
}
// dijkstra
public void dij(int n, int k){
PriorityQueue<Node> queue = new PriorityQueue<>(new Comparator<Node>()
{
@Override
public int compare(Node a, Node b){
return a.dis - b.dis ;
}
}); // 优先队列选择最短的边
for(int i=0;i<n;i++) dis[i] = Integer.MAX_VALUE; //设置初始距离
dis[k] = 0;
queue.offer(new Node(k, 0));
int cnt = 0; // 统计松弛次数
while(!queue.isEmpty()){
Node node= queue.poll();
int u = node.u;
Table table = tables[u];
if(vis[u]!=0) continue;
vis[u] = 1;
// 小优化
cnt ++;
if(cnt >= n) break;
// 标记临近节点
for(int i = 0;i< table.v.size() ;i++){
int w = table.w.get(i);
int v = table.v.get(i);
if(dis[v] > dis[u] + w){
dis[v] = dis[u] + w;
p[v] = u;
queue.offer(new Node(v, dis[v]));
}
}
}
}
public int networkDelayTime(int[][] times, int n, int k) {
// 构造邻接表
init(n+1); // 初始化数组
for(int i = 0;i < times.length;i++) {
tables[times[i][0]].v.add(times[i][1]);
tables[times[i][0]].w.add(times[i][2]);
}
dij(n+1, k); // 调用dijkstra
Arrays.sort(dis); // 最短路径排序
return dis[n-1]==Integer.MAX_VALUE?-1:dis[n-1];
}
}