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 has a weight (a cost or length). The weight of a path is the sum of the weights of its edges. The shortest-path distance is the smallest weight of a path from to ( 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 : .
Relaxation of an edge : if , set and . A relaxation never makes smaller than the true distance, only closer to it.
Dijkstra's algorithm (all ). Keep (an upper bound for , initially , and for ) and a set of finished vertices. Repeat: choose the unfinished vertex with the smallest , mark it finished, and relax all edges leaving (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 , , , , , , , , . Watch vertex : its first estimate (the direct edge) is improved to once vertex is finished, because costs .
Dijkstra's algorithm: finalise the closest unfinished vertex, then relax its edges
Real runC source
dist[v] (blank = infinity)
parent[v]
finished (1 = distance is final)
Edges (u>v:weight)
State
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.
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 3Dijkstra's algorithm round by round: start
Computed by a script, not typed| round | vertex taken | its distance (final) | distances of vertices 0 to 5 afterwards | distances 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.
The vertices are finished in the order with distances : non-decreasing. The parents give the shortest path tree; the shortest path to is read backwards: , that is of weight . Every edge was examined once: relaxation attempts for edges.
Why it is correct
Invariant. When a vertex is finished, .
Proof sketch. Suppose is the first vertex finished with . Look at a shortest path from to and the first vertex on it that is not finished; its predecessor on the path is finished, and by the choice of the distance of is correct, so relaxing gave . Since all weights are non-negative, . But was chosen as the unfinished vertex with the smallest , so : a contradiction.
The non-negativity is used in the step : the rest of the path from to cannot make it shorter.
Why a negative edge breaks it
With the edges , and , Dijkstra finishes vertex first (distance ) and never revisits it, though costs .
Dijkstra with a negative edge: start
Computed by a script, not typed| vertex | Dijkstra's answer | true distance | verdict |
|---|---|---|---|
| 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.
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: costs , while costs and is shorter; add to every edge and the direct edge costs while the two-edge path costs : the shortest path is now the other one. Use Bellman-Ford when negative weights occur.
Running time
The work is: times "find the unfinished vertex with the smallest distance", and relaxations in all (one for each edge, when its tail is finished).
| Priority queue | Find the minimum | Relax (decrease key) | Total |
|---|---|---|---|
| unsorted array (the code above) | |||
| binary min-heap | |||
| Fibonacci heap | amortized | amortized |
For a dense graph () the array version, , is the best of the first two; for a sparse graph () the heap gives . A heap implemented without decrease-key (insert a new entry each time a distance improves and ignore stale entries) has entries and the same bound. Space beyond the graph.
Relatives
- BFS is Dijkstra when every weight is : 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 (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
EasyGraph , , , , . Start: . Finish : , . Finish (distance ): : , so ; : . Finish (distance ): : , so . Finish (). Distances ; the path to is .
EX 2Order of finishing
EasyFor the page graph the vertices are finished in the order : by increasing final distance. The vertex is finished after vertex although its label is smaller, since its distance exceeds . 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, , . Finish : , . The smallest unfinished is (distance ): finish it. Then : the edge would give , but is finished, so nothing changes. Dijkstra reports ; the true distance is . 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?
MediumA road network with junctions and roads: array version steps, heap version about . A complete graph with and (all ordered pairs): array steps, binary heap about : 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: . (c) With a binary heap and adjacency lists: . (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 .
- Invariant: a vertex's dist is final when it is finished; vertices finish in non-decreasing order of distance.
- Time: array/matrix ; binary heap ; Fibonacci heap . 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
Unlocks
Across subjects
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
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)
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 !
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
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 !
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
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
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 vertices and edges?
Show answerHide
, which is for a connected graph.
Question 2
Why does Dijkstra's algorithm need non-negative weights?
Show answerHide
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 answerHide
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 answerHide
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. only.
- Correct because a finished vertex's dist is final; vertices finish in non-decreasing order.
- array; binary heap; 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)