743. 网络延迟时间
有 n 个网络节点,标记为 1 到 n。
给你一个列表 times,表示信号经过 ***有向*** 边的传递时间。
times[i] = (ui, vi, wi),其中 ui 是源节点,vi是目标节点,
wi是一个信号从源节点传递到目标节点的时间。
现在,从***某个节点 K*** 发出一个信号。需要多久才能使所有节点都收到信号?
如果不能使所有节点收到信号,返回 -1 。
提示:
1) 1 <= k <= n <= 100
2) 1 <= times.length <= 6000
3) times[i].length == 3
4) 1 <= ui, vi <= n
5) ui != vi
6) 0 <= wi <= 100
7) 所有 (ui, vi) 对都 互不相同(即,不含重复边)
链接:https://leetcode-cn.com/problems/network-delay-time
这里理解一下题意:
1) 首先这里给的是一个有向图;
2) 给的节点k, 从节点k出发, 使所有节点都收到信号的所需要的的时间.
仅仅看完题目还不够, 因为, 看完题目你还不能真正理解题目的意图,
需要结合例题来看:
在例子中, times = [[2,1,1],[2,3,1],[3,4,1]], n = 4, k = 2,
所需要的时间是2.
在思考过程中就会发现,
这个题以节点k为起点, 求节点k到其他所有节点的最小路径值,
并在所有这些最小路径值中找到最大值.
3) 所以, 这个题可以理解为:
(1) 在有向图中, 以节点k为起点, 求该有向图的最小生成树;
(2) 在最小生成树中,
寻找以节点k为起点, 找到节点k到其他所有节点的路径中的最长路径.
解题思路:
在这里的,解决这道题主要思路是:有向图的层次遍历+最小生成树prim算法.
1) 首先这是一个有向图, 有向图的关系表现在times数组中,
使用times数组和map数据结构构建有向图的邻接关系graphEdges.
2) 层次遍历:使用一个队列deq来记录当前节点可到达的其他节点
3) prim算法思想:
对于每一个当前节点curNode, 遍历curNode的邻接节点,
并更新curNode的邻接节点的最小距离值(这里是消息到达时间).
4) 整个节点都遍历完后,
再从最小生成树里找到起始节点k到达其他节点的最大距离值(消息到达时间)
题目里暗含的一些陷阱:
1) 第一个陷阱---有向图中***存在环***的情况:
(1) 自环: 就是从A节点出发, 不经过其他节点, 最终又指向节点本身.
但是, 提示里面ui != vi, 所以, 有向图里面不会存在自环的情况.
(2) 非自环的其他环:
从A节点出发, 经过若干其他节点后, 最终又回到了A节点本身.
在题目中没有做明确指出不存在环的情况.
所以, 在实际情形中, 会存在其他非自环的情况.
2) 第二个陷阱:
在层次遍历中, 如何判断是否将一个节点加入队列中作为下一次遍历的起始点呢?
(1) 对于无向的联通图而言,
我们可以使用一个visited数组来标记每一个节点是否访问过,
只要当前节点被访问过了就不再加入队列中。
但是, 在这里, 仅仅这样做是行不通的, 因为该图是一个有向的图,
点与点之间不是完全可达的情况.
所以还得再加一个条件:
(2) 如果当前节点curNode的最小距离值更新了,
则将当前节点curNode加入队列中.
3) 第三个陷阱:
回到有向图本身: 在有向图中, 存在点与点之间不可达的情况,
这会导致存在一些点是起始点k不可达的情况,
所以, 需要判断是否存在节点k不可达的其他节点,
若存在这样的节点, 题目明确告诉, 返回-1即可.
java代码
public int networkDelayTime(int[][] times, int n, int k) {
//==========构建有向图的邻接关系, key为出发点, val为一个可到达的点构成的数组列表
Map<Integer,List> graphEdges = new HashMap<>();
for(int i=1<