Dijkstra-leetcode 743.网络延迟时间
743.网络延迟时间
有 N
个网络节点,标记为 1
到 N
。
给定一个列表 times
,表示信号经过有向边的传递时间。 times[i] = (u, v, w)
,其中 u
是源节点,v
是目标节点, w
是一个信号从源节点传递到目标节点的时间。
现在,我们从某个节点 K
发出一个信号。需要多久才能使所有节点都收到信号?如果不能使所有节点收到信号,返回 -1
。
示例:
输入:times = [[2,1,1],[2,3,1],[3,4,1]], N = 4, K = 2
输出:2
注意:
N
的范围在[1, 100]
之间。K
的范围在[1, N]
之间。times
的长度在[1, 6000]
之间。- 所有的边
times[i] = (u, v, w)
都有1 <= u, v <= N
且0 <= w <= 100
。
思路:
信号的传递走的是最短路径,题目要求所有节点都收到信号所需时间,就需要找到最后收到信号的节点。
可以看作从节点K开始,到其他节点的所有最短路径中最长的那一条。
找最短路径使用Dijkstra算法,找到从K开始到其他节点的最短路径,最后从这些最短路径中找出最长的一条返回即可
class Solution {
int INF = (int)Double.POSITIVE_INFINITY; //INF表示无穷大
public int networkDelayTime(int[][] times, int N, int K) {
int[][] matrix = new int[N+1][N+1]; //表示题目节点与边信息的邻接矩阵
int[] dis = new int[N+1]; //储存K到其他节点最短路径
int[] book = new int[N+1]; //记录已经找到最短距离的节点
for(int i=0;i<N+1;i++){
for(int j=0;j<N+1;j++){
matrix[i][j] = INF; //初始化邻接矩阵
}
}
for(int i=0;i<times.length;i++){
matrix[times[i][0]][times[i][1]] = times[i][2]; //通过题目所给信息初始化邻接矩阵
}
for(int i=1;i<N+1;i++){
dis[i] = matrix[K][i]; //根据邻接矩阵为dis赋初值,表示从K能到达的节点的节点距离
}
book[K] = 1; //初始节点置为1
dis[K] = 0; //K到K的距离为0
for(int i=1;i<N+1;i++){
int min = INF;
int u = -1; //Q中最短结点
for(int j=1;j<N+1;j++){ //找到从K出发能到达的最近的节点
if(book[j] == 0 && dis[j] < min ){
min = dis[j];
u = j;
}
}
if(u==-1){
continue;
}
book[u] = 1; //将最短节点标记为已找到
for(int k=1;k<N+1;k++){ //对U的所有出边进行松弛
if( matrix[u][k] < INF ){ //只有U能到达的节点才会进入循环
if(dis[k] > dis[u] + matrix[u][k]){ //如果通过U中转比K直接到新节点路径短
dis[k] = dis[u] + matrix[u][k]; //修改最短距离
}
}
}
}
int ans = -1;
for(int i=1;i<N+1;i++){ //遍历dis,如果还有K到其他节点的距离为INF,表示不能到达,返回-1
if(dis[i] == INF)
return -1;
ans = Math.max(ans,dis[i]);
}
return ans; //返回到其他节点的最远距离
}
}
堆优化版本
class Solution {
int INF = (int)Double.POSITIVE_INFINITY; //无穷大
public int networkDelayTime(int[][] times, int N, int K) {
Queue<Node> queue = new PriorityQueue<>(new MyCompare()); //优先队列,类型为Node
int[][] matrix = new int[N+1][N+1]; //邻接矩阵
int[] dis = new int[N+1]; //储存起点K到其他节点最短距离
int[] book = new int[N+1]; //记录已经找到最短距离的节点
for(int i=0;i<N+1;i++){ //初始化
dis[i] = INF;
for(int j=0;j<N+1;j++){
matrix[i][j] = INF;
}
}
for(int i=0;i<times.length;i++){
matrix[times[i][0]][times[i][1]] = times[i][2];
}
dis[K] = 0;
queue.add(new Node(K,0)); //将起点入队
while( !queue.isEmpty() ){
Node temp = queue.poll(); //取出队列中距离起点最近的节点 u
int u = temp.n;
if( book[u] == 1 )
continue;
book[u] = 1; //因为节点u已经是离起点最近的节点,所以标记为已找到最小路径
for(int i=1;i<N+1;i++){
if( book[i] == 0 && matrix[u][i] != INF){//遍历所有未找到最小路径的节点
if(dis[i] > dis[u] + matrix[u][i]){ //判断是否能通过u进行松弛
dis[i] = dis[u] + matrix[u][i];
queue.add(new Node(i,dis[i]));
}
}
}
}
int ans = -1;
for(int i=1;i<N+1;i++){ //处理结果
if(dis[i] == INF)
return -1;
ans = Math.max(ans,dis[i]);
}
return ans;
}
}
class MyCompare implements Comparator<Node>{ //优先队列比较规则
public int compare(Node n1,Node n2){
if( n1.step > n2.step ){
return 1;
}else{
return -1;
}
}
}
class Node{ //优先队列数据元素
int n; //节点编号
int step; //距离起点的距离
public Node(int a,int b){
n = a ;
step = b;
}
}
理论上堆优化的写法应该比朴素写法快一些,但是提交的时候反而慢一些....暂时不知道原因