G27
Self-checkedTier 1 13 min readalgo.sssp-dijkstra

Dijkstra's algorithm

Single-source shortest paths with non-negative weights: relaxation and the triangle inequality, Dijkstra's algorithm (repeatedly finish the unfinished vertex with the smallest distance and relax its edges), why it is correct and why a negative edge breaks it, running times O(V^2) with an array, O((V + E) log V) with a binary heap and O(E + V log V) with a Fibonacci heap, path reconstruction, and the difference from BFS and from Prim.

Why it exists

A route planner, a network router and a game's path finder all need the cheapest way from one place to all others when every road has a cost. Dijkstra's algorithm does it in nearly linear time whenever no cost is negative. It is a greedy algorithm (always finish the closest unfinished vertex) and a close relative of BFS (which is the special case where all costs are equal) and of Prim's algorithm (the same loop with a different key). GATE asks for the distances and the order in which vertices are finished, the running time for each data structure, and why negative edges are not allowed.

Prerequisites

You need graph search (BFS and DFS) and the min-heap (binary heap).

Precise definitions

Weighted directed graph. Each edge u→vu \to v has a weight w(u,v)w(u, v) (a cost or length). The weight of a path is the sum of the weights of its edges. The shortest-path distance δ(s,v)\delta(s, v) is the smallest weight of a path from ss to vv (∞\infty if there is none). An undirected edge is treated as two directed edges of the same weight.

Optimal substructure. Every subpath of a shortest path is itself a shortest path (otherwise it could be replaced by a shorter one). This is what makes greedy and dynamic programming work.

Triangle inequality. For every edge u→vu \to v: δ(s,v)≤δ(s,u)+w(u,v)\delta(s, v) \le \delta(s, u) + w(u, v).

Relaxation of an edge u→vu \to v: if dist[u]+w(u,v)<dist[v]\text{dist}[u] + w(u, v) < \text{dist}[v], set dist[v]=dist[u]+w(u,v)\text{dist}[v] = \text{dist}[u] + w(u, v) and parent[v]=u\text{parent}[v] = u. A relaxation never makes dist[v]\text{dist}[v] smaller than the true distance, only closer to it.

Dijkstra's algorithm (all w≥0w \ge 0). Keep dist[v]\text{dist}[v] (an upper bound for δ(s,v)\delta(s, v), initially ∞\infty, and 00 for ss) and a set of finished vertices. Repeat: choose the unfinished vertex uu with the smallest dist\text{dist}, mark it finished, and relax all edges leaving uu (to unfinished vertices). Stop when no unfinished vertex has finite distance.

How it works

The animation runs the real code on a directed graph with edges 0→1 (4)0 \to 1\,(4), 0→2 (1)0 \to 2\,(1), 2→1 (2)2 \to 1\,(2), 1→3 (1)1 \to 3\,(1), 2→3 (5)2 \to 3\,(5), 3→4 (3)3 \to 4\,(3), 1→4 (8)1 \to 4\,(8), 4→5 (2)4 \to 5\,(2), 3→5 (6)3 \to 5\,(6). Watch vertex 11: its first estimate 44 (the direct edge) is improved to 33 once vertex 22 is finished, because 0→2→10 \to 2 \to 1 costs 1+21 + 2.

Dijkstra's algorithm: finalise the closest unfinished vertex, then relax its edges

Real run

C source

1#include <stdio.h>
2
3#define N 6
4#define INF 1000000
5
6static int w[N][N]; /* w[u][v] is the weight of the edge u -> v, 0 if there is none (weights are positive) */
7static int done[N];
8
9/* shortest distances from src; parent[] gives the shortest path tree */
10void dijkstra(int src, int dist[], int parent[]) {
11 for (int v = 0; v < N; v++) {
12 dist[v] = INF;
13 parent[v] = -1;
14 done[v] = 0;
15 }
16 dist[src] = 0;
17 for (int round = 0; round < N; round++) {
18 int u = -1;
19 for (int v = 0; v < N; v++) {
20 if (!done[v] && dist[v] < INF && (u == -1 || dist[v] < dist[u])) {
21 u = v;
22 }
23 }
24 if (u == -1) {
25 break;
26 }
27 done[u] = 1;
28 for (int v = 0; v < N; v++) {
29 if (w[u][v] != 0 && !done[v]) {
30 int cand = dist[u] + w[u][v];
31 if (cand < dist[v]) {
32 dist[v] = cand;
33 parent[v] = u;
34 }
35 }
36 }
37 }
38}

dist[v] (blank = infinity)

0
1
2
3
4
5

parent[v]

0
1
2
3
4
5

finished (1 = distance is final)

0
0
0
1
0
2
0
3
0
4
0
5

Edges (u>v:weight)

0>1:4 0>2:1 2>1:2 1>3:1 2>3:5 3>4:3 1>4:8 4>5:2 3>5:6

State

finished vertices = 0 of 6, edge relaxations tried = 0

Blue = the position this step is working on, amber = a position being compared, red = positions just swapped, green = finished or in its final place, a filled blue cell = a value just placed, faded = not part of the structure at this step.

Step 1

A weighted directed graph. Find the shortest distance from vertex 0 to every vertex.

1 / 27
A directed graph with 6 vertices and 9 positive weights is set up by hidden driver code: 0>1:4, 0>2:1, 2>1:2, 1>3:1, 2>3:5, 3>4:3, 1>4:8, 4>5:2, 3>5:6. dijkstra() is the exact code that runs (the simple version with an array scan, O(V^2)). Produced by: real execution: every array, stack, matrix and list in the picture is read from the running program's memory at each step. Apple clang version 21.0.0 (clang-2100.1.1.101). gcc -O0 -o prog prog.c && ./prog

The same run in a table, round by round, from a C program that prints its state after every round and also counts the relaxations tried:

#include <stdio.h>
 
#define N 6
#define INF 1000000
 
static int w[N][N];                  /* w[u][v] = weight of the edge u -> v, 0 if there is none */
 
static void show(const int dist[]) {
    for (int v = 0; v < N; v++) {
        if (dist[v] >= INF) printf(" inf");
        else printf(" %3d", dist[v]);
    }
}
 
int main(void) {
    int dist[N], parent[N], done[N] = {0}, tried = 0;
    w[0][1] = 4; w[0][2] = 1; w[2][1] = 2; w[1][3] = 1; w[2][3] = 5; w[3][4] = 3; w[1][4] = 8; w[4][5] = 2; w[3][5] = 6;
    for (int v = 0; v < N; v++) { dist[v] = INF; parent[v] = -1; }
    dist[0] = 0;
    for (int round = 1; round <= N; round++) {
        int u = -1;
        for (int v = 0; v < N; v++)
            if (!done[v] && dist[v] < INF && (u == -1 || dist[v] < dist[u])) u = v;
        if (u == -1) break;
        done[u] = 1;
        for (int v = 0; v < N; v++) {
            if (w[u][v] != 0 && !done[v]) {
                tried++;
                if (dist[u] + w[u][v] < dist[v]) { dist[v] = dist[u] + w[u][v]; parent[v] = u; }
            }
        }
        printf("round %d: take %d (dist %d), distances:", round, u, dist[u]);
        show(dist);
        printf("\n");
    }
    printf("edge relaxations tried: %d (one for each of the 9 edges)\n", tried);
    printf("parents:");
    for (int v = 0; v < N; v++) printf(" %d", parent[v]);
    printf("\n");
 
    /* a negative edge breaks the method: 0 -> 1 (2), 0 -> 2 (3), 2 -> 1 (-2) */
    int m[3][3] = {{0, 2, 3}, {0, 0, 0}, {0, -2, 0}}, d3[3] = {0, INF, INF}, f3[3] = {0};
    d3[1] = 2; d3[2] = 3;
    for (int round = 0; round < 3; round++) {
        int u = -1;
        for (int v = 0; v < 3; v++) if (!f3[v] && d3[v] < INF && (u == -1 || d3[v] < d3[u])) u = v;
        if (u == -1) break;
        f3[u] = 1;
        for (int v = 0; v < 3; v++) if (m[u][v] != 0 && !f3[v] && d3[u] + m[u][v] < d3[v]) d3[v] = d3[u] + m[u][v];
    }
    int e3[3][3] = {{0, 2, 3}, {0, 0, 0}, {0, -2, 0}}, t3[3] = {0, INF, INF};
    for (int pass = 0; pass < 3; pass++)                  /* the true distances, by trying every edge repeatedly */
        for (int u = 0; u < 3; u++)
            for (int v = 0; v < 3; v++)
                if (e3[u][v] != 0 && t3[u] < INF && t3[u] + e3[u][v] < t3[v]) t3[v] = t3[u] + e3[u][v];
    printf("negative edge example: Dijkstra gives %d %d %d, the true distances are %d %d %d\n", d3[0], d3[1], d3[2], t3[0], t3[1], t3[2]);
    return 0;
}
round 1: take 0 (dist 0), distances:   0   4   1 inf inf inf
round 2: take 2 (dist 1), distances:   0   3   1   6 inf inf
round 3: take 1 (dist 3), distances:   0   3   1   4  11 inf
round 4: take 3 (dist 4), distances:   0   3   1   4   7  10
round 5: take 4 (dist 7), distances:   0   3   1   4   7   9
round 6: take 5 (dist 9), distances:   0   3   1   4   7   9
edge relaxations tried: 9 (one for each of the 9 edges)
parents: -1 2 0 1 3 4
negative edge example: Dijkstra gives 0 2 3, the true distances are 0 1 3

Dijkstra's algorithm round by round: start

Computed by a script, not typed
roundvertex takenits distance (final)distances of vertices 0 to 5 afterwardsdistances that changed (vertices)
round 1
round 2
round 3
round 4
round 5
round 6

Step 0

Distances from vertex 0 on the 6-vertex graph of the animation. A vertex is taken when its distance is the smallest among the unfinished ones; then its outgoing edges are relaxed.

0 / 6
computed by script: the quantities are measured by running C, or evaluated, one row at a time. python3 scripts/gen-algo-paths-traces.py

The vertices are finished in the order 0,2,1,3,4,50, 2, 1, 3, 4, 5 with distances 0,1,3,4,7,90, 1, 3, 4, 7, 9: non-decreasing. The parents −,2,0,1,3,4-, 2, 0, 1, 3, 4 give the shortest path tree; the shortest path to 55 is read backwards: 5←4←3←1←2←05 \leftarrow 4 \leftarrow 3 \leftarrow 1 \leftarrow 2 \leftarrow 0, that is 0→2→1→3→4→50 \to 2 \to 1 \to 3 \to 4 \to 5 of weight 1+2+1+3+2=91 + 2 + 1 + 3 + 2 = 9. Every edge was examined once: 99 relaxation attempts for 99 edges.

Why it is correct

Invariant. When a vertex uu is finished, dist[u]=δ(s,u)\text{dist}[u] = \delta(s, u).

Proof sketch. Suppose uu is the first vertex finished with dist[u]>δ(s,u)\text{dist}[u] > \delta(s, u). Look at a shortest path from ss to uu and the first vertex yy on it that is not finished; its predecessor xx on the path is finished, and by the choice of uu the distance of xx is correct, so relaxing x→yx \to y gave dist[y]=δ(s,y)\text{dist}[y] = \delta(s, y). Since all weights are non-negative, δ(s,y)≤δ(s,u)<dist[u]\delta(s, y) \le \delta(s, u) < \text{dist}[u]. But uu was chosen as the unfinished vertex with the smallest dist\text{dist}, so dist[u]≤dist[y]\text{dist}[u] \le \text{dist}[y]: a contradiction. ■\blacksquare

The non-negativity is used in the step δ(s,y)≤δ(s,u)\delta(s, y) \le \delta(s, u): the rest of the path from yy to uu cannot make it shorter.

Why a negative edge breaks it

With the edges 0→1 (2)0 \to 1\,(2), 0→2 (3)0 \to 2\,(3) and 2→1 (−2)2 \to 1\,(-2), Dijkstra finishes vertex 11 first (distance 22) and never revisits it, though 0→2→10 \to 2 \to 1 costs 3−2=13 - 2 = 1.

Dijkstra with a negative edge: start

Computed by a script, not typed
vertexDijkstra's answertrue distanceverdict
vertex 0
vertex 1
vertex 2

Step 0

The graph has the edges 0 -> 1 (weight 2), 0 -> 2 (weight 3) and 2 -> 1 (weight -2). The true distances were found by trying every edge repeatedly.

0 / 3
computed by script: the quantities are measured by running C, or evaluated, one row at a time. python3 scripts/gen-algo-paths-traces.py

Do not try to repair negative weights by adding a constant to every weight: a path with more edges is penalised more, so the shortest path can change. Example: 0→30 \to 3 costs 55, while 0→1→30 \to 1 \to 3 costs 2+2=42 + 2 = 4 and is shorter; add 33 to every edge and the direct edge costs 88 while the two-edge path costs 1010: the shortest path is now the other one. Use Bellman-Ford when negative weights occur.

Running time

The work is: VV times "find the unfinished vertex with the smallest distance", and EE relaxations in all (one for each edge, when its tail is finished).

Priority queueFind the minimumRelax (decrease key)Total
unsorted array (the code above)Θ(V)\Theta(V)Θ(1)\Theta(1)Θ(V2+E)=Θ(V2)\Theta(V^2 + E) = \Theta(V^2)
binary min-heapΘ(log⁡V)\Theta(\log V)Θ(log⁡V)\Theta(\log V)Θ((V+E)log⁡V)\Theta((V + E) \log V)
Fibonacci heapΘ(log⁡V)\Theta(\log V) amortizedΘ(1)\Theta(1) amortizedΘ(E+Vlog⁡V)\Theta(E + V \log V)

For a dense graph (E≈V2E \approx V^2) the array version, Θ(V2)\Theta(V^2), is the best of the first two; for a sparse graph (E≈VE \approx V) the heap gives Θ(Vlog⁡V)\Theta(V \log V). A heap implemented without decrease-key (insert a new entry each time a distance improves and ignore stale entries) has O(E)O(E) entries and the same O(Elog⁡V)O(E \log V) bound. Space Θ(V)\Theta(V) beyond the graph.

Relatives

  • BFS is Dijkstra when every weight is 11: the queue is the priority queue, because distances come out in non-decreasing order anyway.
  • Prim has the same loop; its key is the weight of one edge to the tree, Dijkstra's key is the total distance from ss (Kruskal and Prim).
  • The shortest paths from one source form a tree (the parents); it is in general not the minimum spanning tree.
  • Dijkstra for a single target can stop as soon as the target is finished.

Worked examples

EX 1Run Dijkstra by hand

Easy

Graph s→a (2)s \to a\,(2), s→b (5)s \to b\,(5), a→b (1)a \to b\,(1), a→c (7)a \to c\,(7), b→c (2)b \to c\,(2). Start: s=0s = 0. Finish ss: a=2a = 2, b=5b = 5. Finish aa (distance 22): bb: 2+1=3<52 + 1 = 3 < 5, so b=3b = 3; cc: 2+7=92 + 7 = 9. Finish bb (distance 33): cc: 3+2=5<93 + 2 = 5 < 9, so c=5c = 5. Finish cc (55). Distances 0,2,3,50, 2, 3, 5; the path to cc is s→a→b→cs \to a \to b \to c.

EX 2Order of finishing

Easy

For the page graph the vertices are finished in the order 0,2,1,3,4,50, 2, 1, 3, 4, 5: by increasing final distance. The vertex 11 is finished after vertex 22 although its label is smaller, since its distance 33 exceeds 11. A question that asks "in which order are the vertices extracted" is asking for this order (ties are broken by label).

EX 3Why negative edges fail

Medium

0→1 (2)0 \to 1\,(2), 0→2 (3)0 \to 2\,(3), 2→1 (−2)2 \to 1\,(-2). Finish 00: dist[1]=2\text{dist}[1] = 2, dist[2]=3\text{dist}[2] = 3. The smallest unfinished is 11 (distance 22): finish it. Then 22: the edge 2→12 \to 1 would give 11, but 11 is finished, so nothing changes. Dijkstra reports 22; the true distance is 11. If finished vertices were allowed to be re-opened the answer would be repaired, but the time bound of the algorithm would no longer hold.

EX 4Which data structure?

Medium

A road network with V=106V = 10^6 junctions and E=3⋅106E = 3 \cdot 10^6 roads: array version Θ(V2)=1012\Theta(V^2) = 10^{12} steps, heap version about (V+E)log⁡2V≈4⋅106⋅20=8⋅107(V + E) \log_2 V \approx 4 \cdot 10^6 \cdot 20 = 8 \cdot 10^7. A complete graph with V=2000V = 2000 and E≈4⋅106E \approx 4 \cdot 10^6 (all ordered pairs): array V2=4⋅106V^2 = 4 \cdot 10^6 steps, binary heap about 4⋅106⋅11=4.4⋅1074 \cdot 10^6 \cdot 11 = 4.4 \cdot 10^7: the array version wins.

EX 5Typical statements

GATE level

(a) Dijkstra's algorithm works correctly with negative edge weights if there is no negative cycle: false. (b) Dijkstra with an adjacency matrix and an array: Θ(V2)\Theta(V^2). (c) With a binary heap and adjacency lists: Θ((V+E)log⁡V)\Theta((V + E) \log V). (d) Adding a positive constant to all weights preserves shortest paths: false. (e) Multiplying all weights by a positive constant preserves shortest paths: true (every path scales by the same factor). (f) The shortest path between two vertices in an undirected graph with positive weights is unique: false in general (ties).

Cheat box

Cheat box

  • Dijkstra: dist, parent, finished flags; repeat: finish the unfinished vertex with the smallest dist, relax its out-edges. Needs all w≥0w \ge 0.
  • Invariant: a vertex's dist is final when it is finished; vertices finish in non-decreasing order of distance.
  • Time: array/matrix Θ(V2)\Theta(V^2); binary heap Θ((V+E)log⁡V)\Theta((V + E) \log V); Fibonacci heap Θ(E+Vlog⁡V)\Theta(E + V \log V). Each edge relaxed once.
  • Fails with negative edges (a finished vertex is never revisited). Adding a constant to all weights does not fix it; scaling by a positive constant keeps shortest paths.
  • Unit weights: BFS. Prim: key = edge weight; Dijkstra: key = path length.
  • Parent pointers give the shortest-path tree; read the path backwards.

Traps and GATE patterns

Connections

Dijkstra is a greedy algorithm built on the binary heap; with all weights equal it is BFS. It is compared with Bellman-Ford, which allows negative edges, and has the same structure as Prim's algorithm.

PYQs

7 previous year questions from your book. I re-solved each one myself (4 by running or simulating, 3 by reasoning only); the book's key is shown next to my answer. All PYQs

GATE 2025 · Set 1 · MCQ · 1 markQ4 · page 113 of the book
Let G be any undirected graph with positive edge
weights, and T be a minimum spanning tree of G.
For any two vertices, u and v, let d1(u,v) and d2(u,v)
be the shortest distances between u and v in G and
T, respectively. Which ONE of the options is
CORRECT for all possible G, T, u and v?
  • (a)d1 (u, v) = d2 (u, v)
  • (b)d1 (u, v) ≤ d2 (u, v)
  • (c)d1 (u, v) ≥ d2 (u, v)
  • (d)d1 (u, v) != d2 (u, v)
GATE 2025 · Set 2 · MCQQ5 · page 113 of the book
Let G be an edge-weighted undirected graph with
positive edge weights. Suppose a positive constant α
is added to the weight of every edge. Which ONE of
the following statements is TRUE about the
minimum spanning trees (MSTs) and shortest paths
(SPs) in G before and after the edge weight update?
  • (a)Every MST remains an MST, and every SP remains an SP.
  • (b)MSTs need not remain MSTs, and every SP remains an SP.
  • (c)Every MST remains an MST, and SPs need not remain SPs.
  • (d)MSTs need not remain MSTs, and SPs need not remain SPs. ALGORITHMS Check Out Our Gate Courses & Secure Your Dream Rank !
GATE 2016 · Set 1 · MCQQ22 · page 116 of the book
Let G be a weighted connected undirected graph
with distinct positive edge weights. If every edge
weight is increased by the same value, then which
of the following statements is/are TRUE?

P: Minimum spanning tree of G does not change
Q: Shortest path between any pair of vertices does
not change
  • (a)P only
  • (b)Q only
  • (c)Neither P nor Q
  • (d)Both P and Q
GATE 2012 · MCQ · 2 marksQ30 · page 117 of the book
Consider the directed graph shown in the figure
below. There are multiple shortest paths between
vertices S and T. Which one will be reported by
Dijkstra's shortest path algorithm? Assume that, in
any iteration, the shortest path to a vertex v is
updated only when a strictly shorter path to v is
discovered.
  • (a)SDT
  • (b)SBDT
  • (c)SACDT
  • (d)SACET 4 ALGORITHMS Check Out Our Gate Courses & Secure Your Dream Rank !
GATE 2008 · MCQ · 2 marksQ37 · page 119 of the book
Dijkstra's single source shortest path algorithm
when run from vertex a in the above graph,
computes the correct shortest path distance to
  • (a)only vertex a
  • (b)only vertices a, e, f, g, h
  • (c)only vertices a, b, c, d
  • (d)all the vertices
GATE 2007 · MCQQ38 · page 119 of the book
Consider a weighted, undirected graph with positive
edge weights and let u v be an edge in the graph. It is
known that the shortest path from the source vertex s
to u has weight 53 and the shortest path from s to v
has weight 65. Which one of the following statements
?
  • (a)Weight(u,v)≤12
  • (b)Weight(u,v)=12
  • (c)Weight(u,v)≥12
  • (d)Weight(u,v)>12
GATE 2005 · MCQ · 1 markQ46 · page 120 of the book
Let G(V,E) be an undirected graph with positive
edge weights. Dijkstra's single source shortest path
algorithm can be implemented using the binary
heap data structure with time complexity:
  • (a)O(|V|2)
  • (b)O(|E| + |V| log |V|)
  • (c)O(|V| log |V|)
  • (d)O((|E| + |V|) log |V|) ALGORITHMS Check Out Our Gate Courses & Secure Your Dream Rank ! i i

Self-check

Question 1

What is the running time of Dijkstra's algorithm with a binary heap on a graph with VV vertices and EE edges?

Show answer

Θ((V+E)log⁡V)\Theta((V + E) \log V), which is Θ(Elog⁡V)\Theta(E \log V) for a connected graph.

Question 2

Why does Dijkstra's algorithm need non-negative weights?

Show answer

Its proof uses that a longer path through unfinished vertices cannot become shorter by adding more edges. A negative edge can lower the distance of a vertex that was already finished and will never be looked at again.

Question 3

In which order does Dijkstra's algorithm finish the vertices?

Show answer

In non-decreasing order of the final shortest-path distance from the source.

Question 4

If all edge weights are doubled, do the shortest paths change?

Show answer

No: every path's weight is doubled, so the same paths are shortest (the distances double).

Revision card

One-screen revision

  • Finish the unfinished vertex with the smallest dist; relax its edges. w≥0w \ge 0 only.
  • Correct because a finished vertex's dist is final; vertices finish in non-decreasing order.
  • Θ(V2)\Theta(V^2) array; Θ((V+E)log⁡V)\Theta((V + E) \log V) binary heap; Θ(E+Vlog⁡V)\Theta(E + V \log V) Fibonacci.
  • Negative edge: wrong. Adding a constant: wrong; scaling: fine. Unit weights = BFS.

References

  • ·Cormen, Leiserson, Rivest, Stein, Introduction to Algorithms (3rd edition), Chapter 24 Single-Source Shortest Paths (24.3 Dijkstra's algorithm)
  • ·Sedgewick and Wayne, Algorithms (4th edition), Section 4.4 Shortest Paths
  • ·Dasgupta, Papadimitriou, Vazirani, Algorithms, Chapter 4 Paths in graphs (4.4 Dijkstra's algorithm)

Verification

On 600 random directed graphs with non-negative weights the distances of Dijkstra (array and heap versions) were compared with a brute force over ALL simple paths and with Bellman-Ford: they agree; vertices were finished in non-decreasing order of distance; every edge out of a finished vertex was relaxed exactly once (9 relaxations on the page graph). With negative edges (no negative cycle) Dijkstra was wrong on many of 600 random graphs and never better than the truth; the three-vertex example of the page was recomputed. Adding a constant to every weight was shown to change the shortest paths. The animation and the table are real runs of the C code on the page. The bounds for the Fibonacci heap are quoted from the textbook. Textbook chapter references are from memory. SECOND PASS (2026-11-02, done by the assistant, not a human check): every Self-check question was solved before the printed answer was read and all agreed; the definitions, worked examples, cheat box and traps were read claim by claim and the numbers re-derived by hand or by a small script (loop counts, recurrences, merge and quicksort counts and averages, hash probes and load-factor formulas, DP tables, MST and shortest-path runs, Floyd matrices); long C programs were not re-read line by line (they are compiled and compared by npm run verify:c, and their printed outputs were checked against the prose); tables and animations are machine output and were read, not re-run; No other defect found. Status raised to self-checked; verified needs a textbook or human check.

last verified: never

My notes (saved in this browser)