Find when a signal from one node reaches every node in a weighted directed graph.
Start with the concrete trace below. It shows the state the algorithm must carry as it runs.
Problem trace
Network Delay Time: Finalize shortest signal times by always popping the cheapest pending path.
Input and goalFind when a signal from one node reaches every node in a weighted directed graph.
Initialize the source pathFor start=1, the min-heap contains only (distance 0, node 1); no node has a finalized distance yet.
visitedfrontier(0,1)
inputn=4, start=1
Finalize node 1 and relax its edgesPop (0,1), finalize distance[1]=0, then push (0+1,2)=(1,2) and (0+4,3)=(4,3).
visited1:0frontier(1,2), (4,3)
relaxation1->2 gives 1; 1->3 gives 4
Finalize node 2Pop (1,2), finalize distance[2]=1, and push (1+2,3)=(3,3) plus (1+6,4)=(7,4).
visited1:0, 2:1frontier(3,3), (4,3), (7,4)
relaxation2->3 gives 3; 2->4 gives 7
Improve the route to node 4Pop (3,3), finalize distance[3]=3, then edge 3->4 pushes (3+1,4)=(4,4), cheaper than the pending (7,4).
visited1:0, 2:1, 3:3frontier(4,3), (4,4), (7,4)
relaxation3->4 gives 4
Skip the stale pathPop (4,3). Node 3 is already finalized at distance 3, so the implementation takes the continue branch and adds no edges.
visited1:0, 2:1, 3:3frontier(4,4), (7,4)
decisionskip duplicate node 3
Finalize the last nodePop (4,4) and finalize distance[4]=4. The later (7,4) is stale and skipped; all four nodes are reached.
visited1:0, 2:1, 3:3, 4:4frontier
decisionskip later (7,4)
Return the network delayThe signal arrival times are {1:0, 2:1, 3:3, 4:4}; the last arrival is max(0,1,3,4)=4.
visited1:0, 2:1, 3:3, 4:4frontier
result4
Recognize it
The input is a directed graph with nonnegative edge costs, and the task asks when a source reaches every node, so shortest paths from one source determine the answer.
Keep true
Whenever an unfinalized node is popped with the globally smallest pending cost, that cost is its shortest distance; duplicate heap entries for finalized nodes are safely ignored.
Reuse it
Reuse Dijkstra for nonnegative weighted routing: enqueue improved path candidates, trust only the first pop of each node, and derive the requested aggregate from finalized shortest distances.
Read it this way: For start=1, the min-heap contains only (distance 0, node 1); no node has a finalized distance yet. Step through the frames to watch the state change. The last frame shows the answer or the stopping condition.
Pattern: Dijkstra.
Simple idea: Always process the path with the lowest total cost next. Add each outgoing
edge cost and put the new path in the heap.
import heapqfrom collections import defaultdictdef network_delay_time(times: list[list[int]], node_count: int, start: int) -> int: graph: dict[int, list[tuple[int, int]]] = defaultdict(list) for source, target, cost in times: graph[source].append((target, cost)) distances: dict[int, int] = {} heap = [(0, start)] while heap: distance, node = heapq.heappop(heap) if node in distances: continue distances[node] = distance for neighbor, cost in graph[node]: if neighbor not in distances: heapq.heappush(heap, (distance + cost, neighbor)) return max(distances.values()) if len(distances) == node_count else -1