150NeetCode 150

95.Network Delay Time

MediumGraphs · 16/19

Problem

There is a network of n nodes labelled 1 to n. You are given times, where times[i] = [u, v, w] means a signal travels along a directed edge from u to v in w time units.

A signal is sent from node k. Return the minimum time it takes for all n nodes to receive it. If some node can never receive the signal, return -1.

Examples

Input:  times = [[2,1,1],[2,3,1],[3,4,1]], n = 4, k = 2
Output: 2
Explanation: Node 1 and 3 receive at t=1, node 4 receives at t=2 via 2 -> 3 -> 4.
Input:  times = [[1,2,1]], n = 2, k = 1
Output: 1
Input:  times = [[1,2,1]], n = 2, k = 2
Output: -1
Explanation: Edges are directed; node 2 cannot reach node 1.

Constraints

  • 1 <= k <= n <= 100
  • 1 <= times.length <= 6000
  • times[i].length == 3
  • 1 <= u, v <= n, u != v
  • 0 <= w <= 100
  • All pairs (u, v) are unique (no multi-edges).

💡 Key Insight

Each node receives the signal at its shortest-path distance from k, and the whole network is done when the farthest node receives it. So the answer is max(dist[v]) over all nodes, or -1 if any distance is infinite. Since all weights are non-negative, Dijkstra's algorithm computes single-source shortest paths in O(E log V).

Floyd-Warshall

TimeO(n³)SpaceO(n²)

Intuition

Compute shortest paths between every pair of nodes with dynamic programming: dist[i][j] is improved by allowing paths that pass through intermediate node m, for each m in turn. Then read the row for k. It is overkill (we only need one source) but very simple.

Algorithm

  1. dist[i][j] = INF, dist[i][i] = 0, and dist[u][v] = w for each edge.
  2. For m in 1..n, for i, for j: dist[i][j] = min(dist[i][j], dist[i][m] + dist[m][j]).
  3. Answer = max(dist[k][v]); if it is INF, return -1.

Visualization

times = [[2,1,1],[2,3,1],[3,4,1]], k = 2

row k=2 initially: [1:1, 2:0, 3:1, 4:INF]
via m=3: dist[2][4] = dist[2][3] + dist[3][4] = 1 + 1 = 2
row k=2 final:     [1:1, 2:0, 3:1, 4:2]  -> max = 2

Code

java
class Solution {
    public int networkDelayTime(int[][] times, int n, int k) {
        final int INF = Integer.MAX_VALUE / 2; // halved to avoid overflow on addition
        int[][] dist = new int[n + 1][n + 1];
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                dist[i][j] = (i == j) ? 0 : INF;
            }
        }
        for (int[] t : times) {
            dist[t[0]][t[1]] = t[2];
        }
        for (int m = 1; m <= n; m++) {
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= n; j++) {
                    if (dist[i][m] + dist[m][j] < dist[i][j]) {
                        dist[i][j] = dist[i][m] + dist[m][j];
                    }
                }
            }
        }
        int answer = 0;
        for (int v = 1; v <= n; v++) {
            answer = Math.max(answer, dist[k][v]);
        }
        return answer >= INF ? -1 : answer;
    }
}

Complexity

  • Time: O(n³) — three nested loops over nodes (10⁶ for n = 100).
  • Space: O(n²) — the distance matrix.

Complexity Comparison

Approach Time Space
Floyd-Warshall O(V³) O(V²)
Bellman-Ford O(V · E) O(V)
Dijkstra's Algorithm O(E log V) O(V + E)

Common Pitfalls

  • Treating the graph as undirected — edges only go from u to v.
  • Nodes are 1-indexed; allocate n + 1 slots and ignore index 0 when taking the max.
  • Returning the sum of distances instead of the maximum.
  • Adding to Integer.MAX_VALUE (overflow) — guard with dist[u] != INF or use a halved INF.
  • Not skipping stale heap entries, which makes Dijkstra re-relax edges from outdated distances.