TLDR
- Two problems share a frontier.One procedure minimises the total length of a spanning tree; the other minimises one route from P to Q.
- Keep one best candidate per outside node.The frontier records the cheapest known attachment or route, replacing it only when a shorter one appears.
- Select the smallest provisional value.The globally smallest frontier candidate is promoted from tentative to permanent.
- Permanence needs an invariant.For shortest paths, non-negative lengths ensure an unsettled route cannot later undercut the node just settled.
- Memory shaped the algorithms.Dijkstra emphasises storing fewer than n frontier and tree branches rather than sorting or retaining every graph edge.
Two optimisation problems, one disciplined frontier
Dijkstra’s note is famously brief, but not slight. It presents a procedure for a minimum-length tree connecting every node and a procedure for a minimum-length path from a chosen node P to a chosen node Q. Both turn a global combinatorial question into repeated local choices whose meaning is carefully maintained.
The setting is a connected weighted graph. Dijkstra calls vertices “nodes”, edges “branches” and weights “lengths”. Some or all pairs of nodes may be connected, and at least one path exists between every pair. Problem 1 seeks a tree spanning all n nodes with minimum total branch length. Problem 2 seeks a path of minimum total length between P and Q.
The two objectives must not be confused. A minimum spanning tree minimises the sum of edges needed to connect everybody; it need not contain the shortest route between any chosen pair. A shortest-path tree records individually shortest routes from one source; its total edge weight need not be the minimum possible connection network. Dijkstra places them together because their constructions share a frontier discipline, not because they solve the same optimisation.
For each problem, some objects are permanent, some are candidates and the rest are unconsidered or rejected. A candidate is not merely “nearby”. It carries the best currently known connexion to a permanent structure. When new information produces a shorter candidate for the same outside node, replacement is immediate. The smallest candidate is then promoted.
That promotion is the intellectual centre. Greedy procedures can be plausible and wrong: a locally short edge might foreclose a better global solution. Here permanence is justified by an invariant. In the spanning-tree problem, the lightest edge crossing the current cut is safe. In the route problem, the smallest tentative distance is final when lengths cannot become negative along a later detour. The paper states the constructions compactly; modern proofs expose why their choices are safe.
Worked example · one map, two answers
Let triangle A–B–C have lengths AB=2, BC=2 and AC=3, and attach D to A for 2 and to C for 1. A minimum spanning tree can use BC, CD and AD for total 5. The shortest A-to-C route is the direct edge of length 3, not the A-to-D-to-C route of length 3 uniquely and not necessarily the route drawn by a chosen minimum tree. “Connect all cheaply” and “reach one destination cheaply” are different contracts.
Causal probe · change the question, keep every edge
Run both procedures on the same weighted graph. If their selected edges differ, nothing has malfunctioned. The intervention changes only the objective: from total network cost to source-relative path cost: and reveals which decisions are consequences of the problem statement rather than of graph geometry alone.
A graph is given through local connexions and lengths
The paper does not begin with a matrix or a modern abstract data type. It begins with points, branches and their lengths, then asks what must be stored simultaneously. Representation and algorithm are designed together.
A path is a sequence of incident branches. Its length is the sum of their lengths. A tree is defined operationally as a graph with exactly one path between each pair of nodes. A spanning tree therefore uses enough branches to connect all n nodes without a cycle; any such tree has n−1 branches. The input graph itself may contain up to n(n−1)/2 undirected branches.
Dijkstra assumes connectedness explicitly. If the graph were disconnected, no tree could span every node and some P-to-Q routes would be absent. A modern implementation can return a minimum spanning forest or infinity for unreachable vertices, but those are extensions. His stopping conditions presuppose that the candidate frontier will keep supplying a next node.
The note calls weights lengths and never discusses negative numbers. Physical length is naturally non-negative. The spanning-tree procedure actually tolerates negative edge weights because its cut argument compares weights without accumulating routes. The shortest-path procedure does not: once a node is declared final, a later path containing a negative edge could make it cheaper. Distinguishing the paper’s language from the modern formal precondition avoids attributing an unstated algebraic theorem to three historical pages.
Dijkstra’s first remark says the route process also applies when branch length depends on traversal direction. That is a directed graph in modern language: w(u,v) may differ from w(v,u). The spanning-tree problem was framed with undirected connexions; directed minimum arborescences are a different problem. One short remark extends Problem 2, not both procedures indiscriminately.
Worked example · direction changes only the route problem
A one-way hill has travel time w(A,B)=2 downhill and w(B,A)=9 uphill. Dijkstra’s first remark permits those two directed lengths in the shortest-path procedure. An undirected spanning tree has one weight per connexion; replacing it with directed costs asks for a rooted arborescence and needs a different safety argument.
Causal probe · insert a negative branch
Give one edge weight −6 while preserving connectivity. The spanning-tree construction can still select a globally minimum tree. The shortest-path construction may settle a node too early and later discover a cheaper route through the negative edge. The same intervention separates a cut-based greedy invariant from a distance-order invariant.
Grow one minimum spanning tree from an arbitrary node
Dijkstra divides branches into permanent set I, candidate set II and remaining set III. Nodes are divided into connected set A and outside set B. Exactly one candidate branch in II leads to each node in B.
Choose any starting node as the sole member of A. Set I is empty. For every outside node directly joined to the start, put its incident branch into II; if the graph is understood through all pairwise computable lengths, each outside node immediately receives one candidate. The candidate represents that node’s cheapest known way to attach to the current subtree.
Step 1 removes the shortest candidate branch from II and makes it permanent in I. Its outside endpoint moves from B to A. Step 2 scans branches from the newly admitted node to nodes still in B. If a scanned branch is longer than that node’s candidate, reject it. If shorter, replace the old candidate and reject the old branch. Then choose the shortest candidate again.
Because every permanent branch introduces exactly one outside node, the permanent edges cannot make a cycle. Connectivity grows by one node per promotion. When B and II are empty, I contains n−1 branches connecting every node: a spanning tree. Ties can produce different trees with the same minimum total length; the procedure need not specify a unique answer.
This is now commonly called Prim’s algorithm, after R. C. Prim’s 1957 paper, although related versions predate both Prim and Dijkstra. Historical naming should not erase the primary’s actual contribution: Dijkstra presents the construction independently, compares its storage with Kruskal and Loberman–Weinberger, and places it beside his shortest-path procedure as a shared frontier pattern.
Worked example · replacement is the work
Start at A with candidates AB=6, AC=3 and AD=8. Promote AC=3. From C discover CB=2 and CD=5, replacing both old candidates. Promote CB=2, then perhaps a new BD=1 replaces CD=5. The final tree uses AC, CB and BD for total 6. The algorithm never needs to keep all rejected alternatives active.
Causal probe · change only the starting node
Run the construction from every vertex. With distinct decisive weights, the selected tree and total should agree despite different promotion orders. Under ties, edge sets may differ while total weight stays minimal. If totals change, candidate replacement or global-minimum selection is wrong.
The lightest crossing edge belongs to some optimum
Dijkstra does not spell out a modern cut-property proof, but the construction preserves its premise. At every stage, the permanent branches form a subtree, and the candidate selected is the lightest edge crossing from that subtree to an outside node.
Let A be the currently connected nodes and choose the minimum-weight branch e crossing from A to V\A. Consider any minimum spanning tree T. If T contains e, the promotion is already compatible with an optimum. If not, add e to T. A cycle appears because T already contains a unique path between e’s endpoints.
That cycle must cross the cut somewhere else, through an edge f. Since e is the lightest crossing edge, w(e)≤w(f). Remove f. The result remains a spanning tree and costs no more than T. Because T was minimum, the exchanged tree is also minimum and now contains e. Thus every promotion can be extended to at least one globally optimal tree.
The proof is an exchange argument, not a claim that the smallest edge anywhere is always safe. Only an edge crossing the cut defined by the existing subtree is eligible. Choosing a tiny edge between two outside nodes could create a separate component and would no longer match Dijkstra’s set invariant, though another algorithm such as Kruskal can safely order edges under a different forest invariant.
Candidate replacement ensures the algorithm actually finds the lightest crossing edge without retaining all of them. For each outside node, any non-minimum attachment to A can never win while its cheaper attachment remains. Taking the minimum over these per-node minima therefore equals taking the minimum over the entire cut. Compression preserves the decision-relevant statistic.
Worked example · exchange one crossing branch
Suppose the current subtree A has a cheapest crossing edge e of weight 4. A proposed optimal tree omits e but crosses the cycle created by adding it through f of weight 6. Replacing f by e lowers total cost, contradicting optimality. If f also weighs 4, replacement keeps cost equal and explains why ties permit several optimum trees.
Causal probe · add a cheap edge entirely outside A
Insert an edge of weight 0.1 between two nodes still in B. Dijkstra’s next choice does not change until one endpoint joins A, because the edge does not yet cross the cut. An implementation that promotes it immediately has silently switched from a single-tree invariant to a forest-based algorithm.
Do not sort or retain what the next decision does not need
Dijkstra compares his tree construction with Kruskal’s 1956 method and with work by Loberman and Weinberger. His stated advantage is simultaneous storage: keep at most n branches in permanent and candidate sets, plus the branch currently under consideration.
Kruskal’s procedure sorts all edges by length, then scans them from shortest upwards, accepting an edge if it connects two different components. In a dense n-node graph there may be n(n−1)/2 edges. Dijkstra argues that sorting and storing all those branches is unnecessary when edge lengths can be computed from node coordinates or otherwise produced as needed.
His frontier representation keeps n−1 or fewer permanent and candidate branches: permanent edges connect the current subtree, while each outside node owns one candidate. When an examined edge cannot improve that node’s attachment, it can be forgotten. The claim concerns simultaneous branch records under a particular access model, not the total number of edge comparisons. A dense graph may still require many lengths to be computed over the entire run.
Modern complexity statements depend on representation. With an adjacency matrix and a linear scan for the minimum key, the spanning-tree procedure takes O(n²) time and O(n) extra frontier storage beyond the matrix. With adjacency lists and a binary heap it takes O((|V|+|E|)log|V|), often written O(|E|log|V|) for connected graphs. A Fibonacci heap gives the classical O(|E|+|V|log|V|) bound. None of this notation appears in the 1959 note.
The historical lesson is more durable than a single asymptotic bound. An algorithm is a policy for information retention. The candidate array is a sufficient summary of every processed crossing edge: only the cheapest attachment per outside node can affect the next choice. Dijkstra’s data structures are therefore part of the proof, not an implementation afterthought.
Worked example · dense coordinates, sparse memory
For 1,000 geometric nodes, a complete graph has 499,500 undirected edges. If every length is calculated from coordinates on demand, storing all edges is avoidable. The frontier needs roughly one key and parent per outside node, though the algorithm may still calculate many pairwise distances. Storage saved is not automatically work saved.
Causal probe · change only graph representation
Run identical mathematics once with an adjacency matrix and once with adjacency lists plus a heap. The selected tree and weight must agree; runtime and memory access can change sharply. This intervention separates the algorithmic invariant from the engineering cost of exposing neighbours and extracting a minimum.
A shortest route contains shortest prefixes
Dijkstra introduces the route procedure with one load-bearing fact: if R lies on a minimum path from P to Q, knowing that path also gives a minimum path from P to R. The global route is built from prefixes that are themselves optimal.
Suppose a minimum P-to-Q path reaches R along a prefix that is not minimum. Replace that prefix with a shorter P-to-R path and retain the remaining suffix from R to Q. The combined route would be shorter than the alleged minimum, a contradiction. This optimal-substructure argument justifies recording one predecessor for each best-known route.
The fact alone does not say which prefix becomes known next. Dijkstra constructs minimal routes from P to other nodes in increasing total length until Q is reached. A node becomes permanent only when its tentative distance is the smallest among all frontier nodes. The distance label, not a single edge length, orders the route frontier.
This distinction separates Problems 1 and 2. The spanning-tree key of an outside node is the cheapest edge connecting it to the tree. The route key is the cheapest total distance from P through already permanent nodes plus one frontier edge. Both records have a parent pointer, but one optimises a network attachment and the other an accumulated source-relative path.
Modern presentations call the update “relaxation”. For a permanent node u and neighbour v, compare the current tentative d[v] with d[u]+w(u,v). If the new route is shorter, replace both distance and predecessor. Dijkstra describes the same operation in prose: the corresponding branch in candidate set II is replaced, and the old branch rejected.
Worked example · a shorter last edge is not a shorter route
P reaches A in 2 and B in 9. Edges A–R and B–R weigh 7 and 1. The last edge from B is shorter, yet the route via A totals 9 while the route via B totals 10. Candidate comparison must use accumulated distance d[parent]+edge, not edge weight alone.
Causal probe · preserve edge weights, move the source
Choose a different P and rerun. The minimum spanning tree objective is source-free, but shortest-path labels, predecessors and settlement order can all change. The intervention exposes source-relative information that must be present in each route candidate.
Settle routes in increasing distance from P
Problem 2 divides nodes into A, B and C. Set A contains nodes whose minimum route from P is known. Set B is the frontier: nodes adjacent to A but not yet permanent. Set C contains the rest.
Branches again occupy sets I, II and III. Set I contains branches forming the permanent minimum paths from P to nodes in A. Set II contains exactly one candidate predecessor branch for each node in B. Set III holds rejected or unexamined branches. Each candidate carries the total distance from P to its farther endpoint, not merely its own branch length.
Initially every node is in C and every branch in III. Transfer P to A with distance zero. Step 1 examines every branch from the newly permanent node to nodes in B or C. A C neighbour enters B with its branch in II. A B neighbour receives the new route only if it is shorter than the route represented by its current candidate.
Step 2 selects the B node with minimum tentative distance, transfers it to A and transfers its candidate branch from II to I. Then Step 1 relaxes the new node’s outgoing branches. Repeat until Q enters A. Stopping at Q is correct because its distance is final on promotion; continuing would construct shortest paths from P to every reachable node.
The predecessor pointers in I form a rooted tree over settled nodes. If several shortest routes tie, the chosen tree depends on tie-breaking even though every recorded distance is correct. Dijkstra’s second remark advises storing each I or II branch with endpoints ordered by increasing distance from P and with the distance to the farther endpoint. That record is recognisably the modern pair parent[v], d[v].
Worked example · an unseen node joins the frontier
After settling A at distance 4, scan edge A–R of weight 3. If R is unseen, it enters B with d[R]=7 and parent A. Later settling B at distance 5 reveals B–R of weight 1, so R’s candidate is replaced by d[R]=6 and parent B. Only when 6 is the smallest frontier value does R become permanent.
Causal probe · stop one step before Q is settled
Finding a tentative route to Q is not enough. Insert another frontier node whose current distance is smaller and whose edge to Q improves the route. If an implementation stops when Q first enters B, it returns too early. The primary stops when Q transfers to A.
The first unsettled vertex on a shortest route cannot be cheaper later
The modern proof follows the boundary between permanent and tentative nodes. Assume all branch lengths are non-negative. When u has the smallest tentative distance in B, no route through an unsettled node can later reduce d[u].
Take a genuinely shortest path from P to u. If it stays inside A until its final edge, relaxation from the last permanent predecessor has already offered its exact length to u. Otherwise let y be the first node on that path outside A and x its permanent predecessor. When x was settled, edge x–y was relaxed, so d[y] is at most the true shortest distance to y.
Non-negative remaining lengths imply δ(P,y)≤δ(P,u): travelling further along the path cannot reduce its accumulated length. Since u was chosen as the smallest tentative node, d[u]≤d[y]. Tentative labels are lengths of actual discovered routes, so δ(P,u)≤d[u]. Chaining the inequalities forces equality. The promoted label is the true minimum.
A negative branch breaks the middle inequality. A route can travel to a currently expensive node, then use a negative edge to become cheaper than an already settled node. The procedure can still work on special graphs containing negative edges, but the simple general guarantee is gone. Bellman–Ford’s repeated relaxation or a valid reweighting method is needed for the broader problem.
Zero-length branches are harmless: they create ties, not reversals. Directed non-negative weights are also harmless, exactly as Dijkstra’s first remark anticipates, provided Step 1 scans outgoing branches in their traversal direction. The proof relies on non-decreasing path length, not on symmetry.
Worked example · force the inequality chain
Suppose u is selected with d[u]=8. On a shortest P-to-u path, first unsettled y has true distance 6. Relaxation guarantees d[y]≤6, while minimum selection says 8=d[u]≤d[y]: a contradiction unless the assumption that u’s true distance is below 8 was wrong. The frontier ordering certifies u.
Causal probe · make a late edge negative
Let P→A cost 2, P→B cost 5 and B→A cost −10. A is settled at 2 before B, but the later route P→B→A costs −5. Change only −10 to +10 and permanence becomes sound again. This smallest counterexample locates the exact proof step supplied by non-negativity.
A proof survives many data structures, not every weight model
Dijkstra specifies branch sets and stored records, not a priority-queue interface. Modern implementations can change how the smallest tentative label is found without changing the invariant that makes settlement final.
An adjacency matrix plus a linear scan produces the familiar O(|V|²) implementation. An adjacency list with a binary heap gives O((|V|+|E|)log|V|); for a connected graph this is commonly simplified to O(|E|log|V|). Decrease-key heaps and specialised integer queues yield other bounds. Those are later engineering refinements, not retroactive details of the three-page primary.
A common implementation pushes a fresh heap entry whenever a tentative distance improves rather than decreasing an existing key. Stale entries are skipped when popped. This may store more than one heap record per frontier node, departing from the primary’s literal one-branch set II, but it implements the same mathematical relaxation if stale records never settle a vertex twice.
Arithmetic belongs inside the contract. Infinity plus a weight must not overflow to a small number; finite integer sums must fit their type; floating-point ties need a declared tolerance only if weights are approximate measurements. A proof over real lengths does not certify a machine implementation whose comparison order is corrupted by overflow or NaN.
The route procedure finds a shortest walk under non-negative weights and can stop at Q. It does not solve longest paths, enumerate all equally short paths, optimise several incomparable costs or handle time-dependent weights without additional assumptions. The tree procedure does not preserve pairwise shortest routes. Naming these boundaries is part of using the algorithms correctly.
Worked example · a stale heap entry
Vertex R first enters with tentative distance 12, then improves to 7. A push-only heap contains both records. When 7 is extracted, settle R. Later extraction of 12 must be ignored because R is already permanent or because 12 differs from its current key. Processing it again can duplicate work or corrupt predecessors.
Causal probe · shrink the integer type
Use an eight-bit unsigned distance and edges 200 and 100. Their mathematical sum is 300 but machine arithmetic wraps to 44. If the algorithm suddenly prefers the two-edge route, the graph invariant is intact while the representation contract has failed. Repeat with checked wide arithmetic to isolate the cause.
Greedy choice works when the frontier summarises every relevant alternative
Both procedures grow a permanent structure, retain one candidate per outside node, replace dominated candidates and promote a global minimum. Their likeness is real; their invariants are not interchangeable.
In Problem 1, key[v] measures the cheapest single edge attaching v to the current tree. The proof uses an exchange across a cut. In Problem 2, d[v] measures the cheapest accumulated route from P whose internal nodes are settled. The proof uses optimal prefixes and non-negative continuation. Writing both as “choose the nearest node” erases the quantity being minimised.
The note’s compactness also reveals a style of algorithm design. Partition knowledge into settled, tentative and unseen. State exactly what one tentative record means. Update only from the object just settled. Promote only when an invariant converts tentative into irrevocable. Stop when the objective is certified, not merely encountered.
Dijkstra claims storage advantages over the compared methods and says the amount of work “seems” considerably less than Ford’s described solution. That is an historically faithful qualitative claim, not a proved modern complexity comparison. Later analysis, data structures and graph models are needed to translate it into asymptotic bounds.
Nothing in the note establishes general agency or intelligence. The procedures have a fixed objective, complete access to declared edge lengths and no learning or preference formation. Their importance for formal agency is architectural: a goal-directed search can act locally without losing global correctness when its state summary and permanence proof are exact.
Worked example · identical loop, different key
With permanent set {P,A}, outside node R has attachment edges of 2 and 5. For the spanning tree its key is 2. If shortest distances are d[P]=0 and d[A]=10, route candidates may be 5 from P and 12 through A, so its distance key is 5. The same parent-update loop computes different sufficient statistics.
Causal probe · swap the two key definitions
Use accumulated route distance in the tree procedure or bare edge length in the route procedure. Each can return a valid connected structure while failing its intended optimum. This swap test proves that surface control flow is not the algorithm; the candidate meaning is.
Run both frontiers over the same weighted graph
Five edge weights reshape a six-node graph. The route laboratory settles distances from A to F; the tree laboratory grows a minimum spanning tree from A. Switch the overlay and inspect where the two objectives share edges or part company.
The fixed edges are B–C=2, C–D=3, D–E=2 and E–F=4. Five independent controls vary the other edges. The audit uses values 1, 3, 5 and 8 for each adjustable weight, giving 4⁵=1,024 positive-weight graphs. Exhaustive spanning-tree enumeration and repeated edge relaxation provide independent reference answers.
Claims, conditions and audit handles
| Claim | Condition | Audit handle |
|---|---|---|
| The first procedure returns a minimum spanning tree. | The graph is connected and branches carry comparable scalar weights. | Compare its n−1 edges with exhaustive spanning-tree enumeration on small graphs. |
| The lightest current attachment is safe. | It is the lightest edge crossing the permanent-subtree cut. | Add it to an alternative optimum and exchange the other cycle edge crossing the cut. |
| The second procedure returns a shortest P-to-Q path. | Accumulated lengths cannot fall along a continuation; non-negative weights suffice. | Compare final distances with Bellman–Ford relaxation or exhaustive simple paths. |
| A tentative distance becomes permanent on selection. | The selected node is globally minimum over the entire frontier B. | Check settled distances are non-decreasing and construct a negative-edge counterexample. |
| Fewer than n branches need simultaneous storage. | Lengths and neighbours can be generated or revisited without storing all edge records. | Count permanent plus one candidate per outside node, separately from input representation. |
| The two procedures are the same greedy algorithm. | Only at the level of control-flow pattern, not objective or proof. | Swap attachment keys and route-distance keys and test both optimisation contracts. |
Twelve cards for rebuilding the note
From active evidence to exact search
Canon 0070 controlled which observation should refine a probability distribution over a hidden Markov state. Canon 0071 begins the formal-agency sequence with complete graph information and exact scalar objectives. Uncertainty recedes; the central question becomes how a local action can be certified against a global goal.
Canon 0072 moves from weighted graphs to propositional quantification in Davis and Putnam’s computing procedure. Dijkstra maintains a cheapest frontier until one node becomes permanent; Davis and Putnam transform and branch over formula structure until satisfiability is decided. Both make search finite by preserving a carefully stated invariant, but the next paper replaces numerical order with logical consequence.
What this companion adds
This companion expands all three pages of the 1959 primary without pretending that later textbook notation appeared there. It reconstructs both problems, all six node and branch sets, both two-step loops, the storage argument, the directed-length remark, the predecessor record and the paper’s four cited predecessors.
Ten original animated figures, ten worked examples and ten causal probes separate minimum total connection from minimum route, edge keys from accumulated-distance keys, historical storage claims from later time bounds, and source language from the modern non-negative-weight precondition. Exchange and invariant proofs are clearly marked as interpretive reconstructions rather than quotations from the terse note.
The executable laboratory evaluates 1,024 weighted graphs. Its Dijkstra distances are checked against repeated relaxation, its spanning-tree weights against exhaustive enumeration, and both predecessor structures against independent validity certificates. The boundary section keeps fixed-objective graph search distinct from broad claims about learning, autonomy or consciousness.
Primary and comparative sources
- E. W. Dijkstra, “A Note on Two Problems in Connexion with Graphs”, Numerische Mathematik 1, 269–271 (1959). Publisher record; CWI primary scan.
- Centrum Wiskunde & Informatica repository record for Dijkstra’s paper. Archival record.
- R. C. Prim, “Shortest Connection Networks and Some Generalizations”, Bell System Technical Journal 36(6), 1389–1401 (1957). Publisher DOI.
- J. B. Kruskal, Jr., “On the Shortest Spanning Subtree of a Graph and the Traveling Salesman Problem”, Proceedings of the American Mathematical Society 7(1), 48–50 (1956). Publisher DOI.
- L. R. Ford, Jr., Network Flow Theory, RAND Corporation Paper P-923 (1956). RAND record.
- M. L. Fredman and R. E. Tarjan, “Fibonacci Heaps and Their Uses in Improved Network Optimization Algorithms”, Journal of the ACM 34(3), 596–615 (1987). Publisher DOI.
- D. B. Johnson, “Efficient Algorithms for Shortest Paths in Sparse Networks”, Journal of the ACM 24(1), 1–13 (1977). Publisher DOI.