Skip to content

743. Network Delay Time

You are given a network of n nodes, labeled from 1 to n. You are also given times, a list of travel times as directed edges times[i] = (ui, vi, wi), where ui is the source node, vi is the target node, and wi is the time it takes for a signal to travel from source to target.

We will send a signal from a given node k. Return the minimum time it takes for all the n nodes to receive the signal. If it is impossible for all the n nodes to receive the signal, return -1.

Example 1:

img

Input: times = [[2,1,1],[2,3,1],[3,4,1]], n = 4, k = 2
Output: 2

Example 2:

Input: times = [[1,2,1]], n = 2, k = 1
Output: 1

Example 3:

Input: times = [[1,2,1]], n = 2, k = 2
Output: -1

Constraints:

  • 1 <= k <= n <= 100
  • 1 <= times.length <= 6000
  • times[i].length == 3
  • 1 <= ui, vi <= n
  • ui != vi
  • 0 <= wi <= 100
  • All the pairs (ui, vi) are unique. (i.e., no multiple edges.)

Solution:

class Solution {
    public int networkDelayTime(int[][] times, int n, int k) {
        int result = Integer.MIN_VALUE;
        // Create the graph as an adjacency list
        Map<Integer, List<int[]>> graph = new HashMap<>();

        for (int[] time : times){
            int source = time[0];
            int target = time[1];
            int weight = time[2];

            graph.putIfAbsent(source, new ArrayList<>());
            graph.get(source).add(new int[]{target, weight});
        }

        int[] dist = dijkstra(graph, n, k);

        for (int i = 1; i < dist.length; i++){
            result = Math.max(result, dist[i]);
        }

        if (result == Integer.MAX_VALUE){
            return -1;
        }else{
            return result;
        }
    }

    private int[] dijkstra(Map<Integer, List<int[]>> graph, int n, int source){
        // Step 1: Initialize-Single-Source
        int[] dist = new int[n + 1];
        Arrays.fill(dist, Integer.MAX_VALUE); // // Set all distances to infinity
        dist[source] = 0; // // Distance to the source node is 0


        // Step 2: Create the set S (visited)
        Set<Integer> visited = new HashSet<>();

        PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> (a[1] - b[1]));
        // minHeap
        pq.offer(new int[]{source, 0}); // Distance to the source node is 
        // {source dist}

        // Step 6: While Q is not empty
        while(!pq.isEmpty()){
            // // Step 7: Extract-Min from the queue
            int[] cur = pq.poll();
            int curNode = cur[0];
            int curDist = cur[1];

            // If the node is already visited, skip it
            if (visited.contains(curNode)){
                continue;
            }

             // Step 8: Add u to the visited set
             visited.add(curNode);

             // Step 9: For each adjacent vertex v in the adjacency list of u
             if (graph.containsKey(curNode)){
                for (int[] nei : graph.get(curNode)){
                    int nextNode = nei[0];
                    int nextWeight = nei[1];

                    // Step 10: Relax the edge (u, v)
                    if (curDist + nextWeight < dist[nextNode]){
                        dist[nextNode] = curDist + nextWeight;
                        pq.offer(new int[]{nextNode, dist[nextNode]});
                    }
                }
             }

        }

        return dist;


    }



}

// TC: O((E+V)logV)
// SC: O(E+Vss)
class Solution {
    // Adjacency list
    Map<Integer, List<Pair<Integer, Integer>>> adj = new HashMap<>();
    //The adjacency list (adj) is a map where the key is a node, and the value is a list of pairs. Each pair contains the travel time to a neighboring node and the neighboring node itself.
    // adj:   , <>
    //     2, <1, 1>       [2]-1->[1]
    //     2, <1, 3>       [2]-1->[3]
    //     3, <1, 4>       [3]-1->[4]

    public int networkDelayTime(int[][] times, int n, int k) {
        for (int[] time : times){ // [2,1,1]; [2,3,1];[3,4,1]
            int source = time[0]; // 2 //  2,
            int dest = time[1]; // 1 //  3
            int travelTime = time[2]; // 1 // 1 

            adj.putIfAbsent(source, new ArrayList<>()); 
            adj.get(source).add(new Pair(travelTime, dest));
        }

        // Iterate through the times array to build the adjacency list. For each time array, extract the source node, destination node, and travel time. Add these to the adjacency list.

        int[] signalReceivedAt = new int[n + 1];
        // [4+ 1] =[5]   
        // 0 1 2 3 4 
        //[0,0,0,0,0]


        Arrays.fill(signalReceivedAt, Integer.MAX_VALUE);
        // 0 1 2 3 4 
        //[-,-,-,-,-]

        // Initialize an array signalReceivedAt to store the minimum time at which each node receives the signal. Initially, set all values to Integer.MAX_VALUE (a large number representing infinity).

        dijkstra(signalReceivedAt, k, n);

        int result = Integer.MIN_VALUE;

        for (int i = 1; i <= n; i++){
            result = Math.max(result, signalReceivedAt[i]);
        }

        if (result == Integer.MAX_VALUE){
            return -1;
        }else{
            return result;
        }
        // Find the maximum value in the signalReceivedAt array, which represents the time it takes for the signal to reach the furthest node. If this value is Integer.MAX_VALUE, it means not all nodes are reachable, so return -1. Otherwise, return the maximum delay time.


    }

    private void dijkstra(int[] signalReceivedAt, int k, int n){
        // PriorityQueue<Pair<Integer, Integer>> pq = new PriorityQueue<Pair<Integer, Integer>>(
        //     Comparator.comparing(Pair::getKey)
        // );
        // PriorityQueue<Pair<Integer, Integer>> pq = new PriorityQueue<Pair<Integer, Integer>>(
        //     new Comparator<Pair<Integer,Integer>>(){
        //         @Override
        //         public int compare(Pair<Integer, Integer> p1, Pair<Integer,Integer> p2){
        //             return Integer.compare(p1.getKey(), p2.getKey());
        //         }
        //     }
        // );
        PriorityQueue<Pair<Integer, Integer>> pq = new PriorityQueue<Pair<Integer, Integer>>(
            new Comparator<Pair<Integer,Integer>>(){
                @Override
                public int compare(Pair<Integer, Integer> p1, Pair<Integer,Integer> p2){
                    if (p1.getKey() < p2.getKey()){
                        return -1;
                    }else if (p1.getKey() > p2.getKey()){
                        return 1;
                    }else{
                        return 0;
                    }
                }
            }
        );


        pq.add(new Pair(0, k)); // pq: [0, 2]


        signalReceivedAt[k] = 0; // 
        // 0 1 2 3 4 
        //[-,-,0,-,-]

        // Use a priority queue (pq) to always process the node with the smallest known distance. Initialize it with the starting node k and set the signal received time for k to 0.




        while(!pq.isEmpty()){
            // pq: <1,3>
            Pair<Integer, Integer> topPair = pq.poll(); // [0,2];//  <1,1> // <1,3>
            // cost, source 

            int currNode = topPair.getValue();// 2 // 1// 3 
            int currNodeTime = topPair.getKey(); // 0 // 1 // 1

            if (currNodeTime > signalReceivedAt[currNode]){
                continue;
            }

     // adj:   , <>
    //     2, <1, 1>       [2]-1->[1]
    //     2, <1, 3>       [2]-1->[3]
    //     3, <1, 4>       [3]-1->[4]

            if (!adj.containsKey(currNode)){
                continue;
            }
            //     2, <1, 1>       [2]-1->[1]
            //     2, <1, 3>       [2]-1->[3]
            //  更新邻居节点的信号接收时间,如果找到更短的路径
            for (Pair<Integer, Integer> edge : adj.get(currNode)){  // <1, 1>, <1,3>, 
                int time = edge.getKey(); // 1 // 1  // 1
                int neighborNode = edge.getValue(); // 1// 3
        // 0 1 2 3 4 
        //[-,1,0,1,-]
                if (signalReceivedAt[neighborNode] > currNodeTime + time){
                    // signalReceivedAt[1] = - > 0 + 1 = 1
                    // signalReceivedAt[3] = - > 0 + 1 = 1
                    // 
                    signalReceivedAt[neighborNode] = currNodeTime + time;
                    pq.add(new Pair(signalReceivedAt[neighborNode], neighborNode));
                    // <1, 1>, <1, 3>
                }
            }
        }
        // While the priority queue is not empty, process each node by updating the signal received time for its neighbors if a shorter path is found. Add these neighbors to the priority queue to continue processing.
    }
}
// TC: O(n+elogn)
// SC: O(n)

After solving this using Dijkstra−algorithm you can implement this in the following questions 787. Cheapest Flights Within K Stops 778. Swim in Rising Water 815. Bus Routes 1091. Shortest Path in Binary Matrix 1631. Path With Minimum Effort 2812. Find the Safest Path in a Grid 2642. Design Graph With Shortest Path Calculator

import java.util.*;

class Solution {
    public int networkDelayTime(int[][] times, int n, int k) {
        // Create a graph representation using a HashMap
        Map<Integer, List<int[]>> edges = new HashMap<>();
        for (int[] time : times) {
            edges.computeIfAbsent(time[0], x -> new ArrayList<>()).add(new int[]{time[1], time[2]});
        }

        // Min-heap priority queue, to always expand the smallest distance node first
        PriorityQueue<int[]> minHeap = new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));
        minHeap.offer(new int[]{0, k});

        // Set to track visited nodes
        Set<Integer> visited = new HashSet<>();
        int t = 0;

        // Dijkstra's algorithm main loop
        while (!minHeap.isEmpty()) {
            int[] current = minHeap.poll();
            int w1 = current[0];
            int n1 = current[1];

            if (visited.contains(n1)) {
                continue;
            }

            visited.add(n1);
            t = Math.max(t, w1);

            // Explore the neighbors of the current node
            if (edges.containsKey(n1)) {
                for (int[] neighbor : edges.get(n1)) {
                    int n2 = neighbor[0];
                    int w2 = neighbor[1];
                    if (!visited.contains(n2)) {
                        minHeap.offer(new int[]{w1 + w2, n2});
                    }
                }
            }
        }

        // Check if all nodes have been visited
        return visited.size() == n ? t : -1;
    }
}