PrepStack · Markdown HTML

Dijkstra nonnegative shortest path

Ordered frontier and path · HTML

Formal shape

Set dist[s]=0. Relax u→v with w≥0 by cand=dist[u]+w. A minimum non-stale label popped from the heap is final.

Recognition signals

False friends

SignalWhy it is different
Negative edge weightA negative detour can improve an already popped label, invalidating Dijkstra's greedy proof.
Minimize the maximum stepThe path aggregator is max rather than addition; use minimax-dijkstra.

Core invariant

A non-stale popped label (d,u) is the smallest unsettled label, and nonnegative extensions cannot create a future route to u below d.

State, transition, and processing order

ItemDefinition
StateTentative sum dist[v], min-heap entries (distance,node), and optional parent pointers.
TransitionFor u→v,w compute nd=d+w; if nd improves dist[v], assign it and push the new label.
Frontier / orderA min-heap ordered by tentative distance; Python uses duplicate pushes plus lazy deletion instead of decrease-key.

Python skeleton

import heapq

def dijkstra(graph, start, goal=None):
    dist = {start: 0}
    heap = [(0, start)]
    while heap:
        d, u = heapq.heappop(heap)
        if d != dist.get(u):
            continue
        if goal is not None and u == goal:
            return d
        for v, w in graph.get(u, []):
            if w < 0:
                raise ValueError('negative edge')
            nd = d + w
            if nd < dist.get(v, float('inf')):
                dist[v] = nd
                heapq.heappush(heap, (nd, v))
    return dist if goal is None else float('inf')

Correctness sketch

  1. Suppose a popped minimum fresh label u had a shorter route. On that route, the first unsettled vertex follows a settled predecessor that would have generated a smaller label, a contradiction.
  2. Relaxing every outgoing edge considers every path prefix capable of improving a destination.
  3. Skipping a stale heap entry discards only a superseded label, never the current best label.

Complexity

TimeSpaceParameters
O((V+E) log H), commonly O(E log V)O(V+H); lazy heaps can reach H=O(E)V is vertices, E edges, and H simultaneous heap labels. A theoretical decrease-key heap keeps at most one handle per vertex; duplicate-push Python is also written O(E log E), with log E=O(log V) for simple graphs.

Edge cases

Error patterns

PatternWhy it fails / fix
Pre-visiting the sourceInitializing visited with start and then skipping visited pops discards the source itself.
Finalizing on pushA later route may improve a discovered vertex; finality belongs to a fresh pop.
Pushing without assigning distHeap insertion and dist assignment must occur in the same successful relaxation.

Selection and exclusion rules

RelationTemplateBoundary
alternativeGrid dynamic programmingNonnegative weighted movement in arbitrary directions contains cycles.
structural-analogyK-way merge heapThe frontier is generated by state expansion and several paths can reach one state.
different path algebraMinimax / bottleneck DijkstraSummation changes to minimizing the largest step.

Original micro-example

PartDetail
ResultThe minimum sum from s to a is 3.
Setups→a costs 7, s→b costs 2, and b→a costs 1.
TracePush a:7 and b:2; popping b improves a to 3; a:3 pops before stale a:7.

Recall prompts

My notes