743. 网络延迟时间| 8月更文挑战

138 阅读2分钟

有 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. 先构建图的邻接矩阵,使用权重填充有向边对应的元素
  2. 使用最小堆,小根堆中的元素为{起点出发到当前节点的距离,当前节点的标号},以有向边的权值进行比较
  3. 每次选择最小边,且没到遍历过的节点进行操作,将相邻的节点入队
  4. 直到所有节点都遍历完一次为止,如果不能遍历完所有的节点则返回-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;
   
    }
}