Kruskal and Prim
The two classic minimum spanning tree algorithms: Kruskal (sort the edges, add each edge that joins two different trees, with union-find using union by rank and path compression) and Prim (grow one tree by the cheapest edge leaving it, with an array in O(V^2) or a binary heap in O(E log V)); their correctness from the cut property, running times, how they compare, and traces on a 7-vertex graph.
Why it exists
The cut property (spanning trees) says which edges are safe; this page says how to find them quickly. Kruskal's algorithm looks at the edges in order of weight and keeps those that do not close a cycle, using a disjoint-set structure to test cycles fast. Prim's algorithm grows one tree from a start vertex, always adding the cheapest edge that leaves the tree, using a priority queue (the same idea as Dijkstra's algorithm). GATE asks for the edges in the order they are added, the total weight, which algorithm suits which graph, and the exact running times.
Prerequisites
You need the cut property and spanning trees (spanning trees and the cut property); for Prim's heap version the binary heap (binary heap).
Precise definitions
Disjoint-set (union-find) structure. It keeps a partition of elements into sets and supports make-set, find (the representative of the set containing ) and union (merge the two sets). Each set is a tree of parent pointers; the root is the representative. Two heuristics: union by rank (attach the shallower tree below the root of the deeper one) keeps the height at most ; path compression (in find, point every node on the path directly at the root) flattens the trees. With both, a sequence of operations on elements takes time, where is the inverse Ackermann function, below for every practical : effectively constant.
Kruskal's algorithm. Sort the edges by weight. Make each vertex a set. For each edge in order: if , add the edge to the tree and union the two sets; otherwise skip it (it would close a cycle). Stop after edges.
Prim's algorithm. Pick a root. Keep for every vertex outside the tree a : the weight of the cheapest edge joining to the tree (infinity if none), and the tree end of that edge. Repeatedly take the vertex outside the tree with the smallest key, add it (and the edge to its parent) to the tree, and for each neighbour outside the tree with set and .
How it works
Kruskal, step by step
The graph has vertices and edges, listed here in order of weight: , , , , , , , , , , . The animation is the real code including the union-find; the row "the set of each vertex" shows the root of each vertex's tree, so you can see the sets merge.
Kruskal's algorithm: take the cheapest edge that does not close a cycle
Real runC source
chosen (1 = in the tree, 0 = rejected, blank = not yet looked at)
weight of edge i (the edges are sorted by weight)
one end of edge i
other end of edge i
the set (tree) of each vertex = its root in the union-find forest
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 graph with 7 vertices and 11 edges, listed in order of increasing weight. Find a minimum spanning tree.
The first six edges are accepted (each joins two different trees); after the sixth, edge with weight , there is one tree of edges and weight , and the remaining five edges all have both ends in the same tree and are rejected. A spanning tree of vertices has exactly edges, so the algorithm can stop as soon as it has accepted edges.
Correctness. When Kruskal accepts , and are in different trees and of the current forest. Take the cut : it respects the chosen edges, and the edge crosses it. Every edge lighter than was looked at earlier and either was chosen (then it lies inside a tree, not across this cut) or was rejected (both ends in the same tree); so is the lightest crossing edge, i.e. light, hence safe by the cut property.
Running time. Sorting: . The loop: find operations and at most unions: , which is dominated by the sort. Since we have , so . If the edges are already sorted (or can be sorted by counting sort because weights are small integers) the rest is nearly linear.
Prim, step by step
The same graph, as a weight matrix, from vertex . The animation shows the in-tree flags, the keys (blank = infinity) and the parents.
Prim's algorithm: grow one tree by the cheapest edge leaving it
Real runC source
in the tree (1 = yes)
key[v] (blank = infinity)
parent[v]
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
The same weighted graph. Prim's algorithm grows ONE tree from vertex 0.
Vertex joins with key ; its neighbours and get keys and . The cheapest outside vertex is (key ); that lowers the key of to (via the edge ) and gives the key . Then (key ), which lowers the key of to ; then (key ), then (key ), (key ) and (key ): total . Prim added the edges in a different order from Kruskal but chose the same tree (all weights are distinct, so the MST is unique).
Correctness. At each step the cut respects the chosen edges, and Prim adds the lightest edge crossing it: safe by the cut property.
Running time depends on the data structure for the keys.
| Structure for finding the smallest key | Time |
|---|---|
| unsorted array (scan all vertices each round), adjacency matrix | |
| binary min-heap, adjacency lists | for a connected graph |
| Fibonacci heap |
With a heap, each vertex is extracted once ( extractions of ) and each edge may lower a key once ( decrease-key operations of in a binary heap).
Which to use
- Sparse graph ( about ): both are ; Kruskal is simplest if the edges come as a list.
- Dense graph ( about ): Prim with an array and a matrix, , beats Kruskal's .
- Kruskal works on a forest (disconnected graph) and returns a minimum spanning forest; Prim as written needs a connected graph (or a restart for each component).
Both agree
The program runs both algorithms, on the page graph and on random connected graphs with vertices and random weights from to (so there are many ties), and compares the total weights.
#include <stdio.h>
#include <stdlib.h>
#define MAXN 12
#define INF 1000000
struct edge { int u, v, w; };
static int parent_[MAXN], rank_[MAXN];
static int find(int x) { if (parent_[x] != x) parent_[x] = find(parent_[x]); return parent_[x]; }
static int unite(int a, int b) {
int ra = find(a), rb = find(b);
if (ra == rb) return 0;
if (rank_[ra] < rank_[rb]) { int t = ra; ra = rb; rb = t; }
parent_[rb] = ra;
if (rank_[ra] == rank_[rb]) rank_[ra]++;
return 1;
}
static int by_weight(const void *a, const void *b) { return ((const struct edge *)a)->w - ((const struct edge *)b)->w; }
/* Kruskal: n vertices, m edges; returns the weight of a minimum spanning tree */
static int kruskal(int n, struct edge e[], int m) {
int total = 0;
qsort(e, (size_t)m, sizeof e[0], by_weight);
for (int v = 0; v < n; v++) { parent_[v] = v; rank_[v] = 0; }
for (int i = 0; i < m; i++) if (unite(e[i].u, e[i].v)) total += e[i].w;
return total;
}
/* Prim from vertex 0 on a weight matrix (0 = no edge) */
static int prim(int n, int w[MAXN][MAXN]) {
int key[MAXN], in_tree[MAXN] = {0}, total = 0;
for (int v = 0; v < n; v++) key[v] = INF;
key[0] = 0;
for (int round = 0; round < n; round++) {
int u = -1;
for (int v = 0; v < n; v++) if (!in_tree[v] && (u == -1 || key[v] < key[u])) u = v;
in_tree[u] = 1;
total += key[u];
for (int v = 0; v < n; v++) if (w[u][v] && !in_tree[v] && w[u][v] < key[v]) key[v] = w[u][v];
}
return total;
}
int main(void) {
struct edge e[11] = {{0, 1, 4}, {0, 2, 9}, {1, 2, 2}, {1, 3, 8}, {2, 3, 6}, {2, 4, 10}, {3, 4, 3}, {3, 5, 12}, {4, 5, 5}, {4, 6, 11}, {5, 6, 7}};
int w[MAXN][MAXN] = {{0}};
for (int i = 0; i < 11; i++) { w[e[i].u][e[i].v] = e[i].w; w[e[i].v][e[i].u] = e[i].w; }
printf("page graph: Kruskal %d, Prim %d\n", kruskal(7, e, 11), prim(7, w));
unsigned s = 20240601;
int agree = 0, trials = 2000, edges_total = 0;
for (int t = 0; t < trials; t++) { /* random connected graphs on 8 vertices, random weights (ties allowed) */
int n = 8, m = 0;
struct edge g[64];
int mat[MAXN][MAXN] = {{0}};
for (int v = 1; v < n; v++) { /* a random tree first, so the graph is connected */
s = s * 1103515245u + 12345u;
int u = (int)((s >> 8) % (unsigned)v);
s = s * 1103515245u + 12345u;
int wt = 1 + (int)((s >> 8) % 20);
mat[u][v] = mat[v][u] = wt;
}
for (int k = 0; k < 10; k++) { /* then some more edges */
s = s * 1103515245u + 12345u;
int u = (int)((s >> 8) % n);
s = s * 1103515245u + 12345u;
int v = (int)((s >> 8) % n);
s = s * 1103515245u + 12345u;
int wt = 1 + (int)((s >> 8) % 20);
if (u != v && !mat[u][v]) mat[u][v] = mat[v][u] = wt;
}
for (int u = 0; u < n; u++) for (int v = u + 1; v < n; v++) if (mat[u][v]) { g[m].u = u; g[m].v = v; g[m].w = mat[u][v]; m++; }
edges_total += m;
if (kruskal(n, g, m) == prim(n, mat)) agree++;
}
printf("random connected graphs on 8 vertices: Kruskal and Prim gave the same weight in %d of %d (average %d edges)\n", agree, trials, edges_total / trials);
return 0;
}page graph: Kruskal 27, Prim 27
random connected graphs on 8 vertices: Kruskal and Prim gave the same weight in 2000 of 2000 (average 12 edges)Kruskal and Prim find the same minimum weight: start
Computed by a script, not typed| input | Kruskal weight | Prim weight | result |
|---|---|---|---|
| the page graph (7 vertices, 11 edges) | |||
| 2000 random connected graphs on 8 vertices |
Step 0
Both algorithms are the code of this page. They were run on the example graph and on random graphs, and the total weights compared.
The weights always agree. With tied weights the trees may differ (several MSTs exist) and so can the order in which edges are added.
Worked examples
EX 1Kruskal on a small graph
EasyEdges: , , , , . Sorted: , , , , . Take (joins , ). Take (joins , ). Take (joins and ). Three edges for vertices: done. Weight . The edges and would not even be looked at if we stop at edges; they would have been rejected (cycles).
EX 2Prim on the same graph from A
EasyKeys: , , . Take (key ): : , : . Take (key ): : . Take (key ). Weight , the same tree . Order of addition: .
EX 3Union-find by hand
MediumElements , each its own set. : roots and , equal rank : attach below and rank of becomes . : below . : ranks and are equal: attach below , rank . walks and with path compression makes point to directly. The height never exceeds .
EX 4When ties matter
MediumA triangle with all three edges of weight : Kruskal (with a stable sort) takes the first two edges in the list and rejects the third; a different order of the list gives a different but equally good tree: there are MSTs, all of weight . Which edges are "in the MST" depends on tie-breaking; the weight does not.
EX 5Typical statements
GATE level(a) Kruskal's running time with a sort and union-find on edges and vertices: , i.e. . (b) Prim with an adjacency matrix and an array: . (c) Prim with a binary heap: . (d) Kruskal and Prim always give the same tree: false with ties; the same weight, true. (e) In Kruskal's algorithm with edges sorted, how many edges are examined before the tree is complete? Up to all , in the worst case (the heaviest edge may be needed). (f) If all weights are distinct, in what order does Kruskal's algorithm add the edges? Increasing weight (of the accepted ones). (g) Which is better for a dense graph? Prim with an array, .
Cheat box
Cheat box
- Kruskal: sort edges; add an edge iff its ends are in different sets (union-find); stop at edges. .
- Prim: grow one tree; key[v] = cheapest edge to the tree; take the smallest key. Array/matrix ; binary heap ; Fibonacci heap .
- Both correct by the cut property; same total weight; trees can differ under ties.
- Union-find: union by rank (height ) + path compression: per operation.
- Dense graph: Prim with array. Sparse: either. Kruskal handles disconnected graphs (forest).
- Kruskal adds edges in increasing weight; Prim adds the cheapest edge leaving the tree.
Traps and GATE patterns
Connections
Builds on
Across subjects
Both algorithms apply the cut property of spanning trees as a greedy algorithm; Prim's heap version uses the binary heap and is almost the same code as Dijkstra's algorithm (the key is an edge weight instead of a path length).
PYQs
9 previous year questions from your book. I re-solved each one myself (8 by running or simulating, 1 by reasoning only); the book's key is shown next to my answer. All PYQs
The number of distinct minimum-weight spanning trees of the following graph is .
Consider a graph G = (V, E), where V = {v 1 , v 2 ,
..., v 100 }, E = {(v i , v j ) | 1 <= i <= j <= 100}, and
weight of the edge (v i , v j ) is |i – j|. The weight of
the minimum spanning tree of G is .
ALGORITHMS
Check Out Our Gate Courses & Secure Your Dream Rank !
5The graph shown below has 8 edges with distinct
integer edge weights. The minimum spanning
tree (MST) is of weight 36 and contains the edges:
{(A, C), (B, C), (B, E), (E, F), (D, F)}. The edge
weights of only those edges which are in the MST
are given in the figure shown below. The
minimum possible sum of weights of all 8 edges
of this graph isAn undirected graph G(V,E) contains n (n > 2) nodes named v1, v2... vn. Two nodes vi , vj are connected if and only if 0 < | i- j | < = 2 . Each edge ( vi, vj )is assigned a weight i + j. A sample graph with n = 4 is shown below. What will be the cost of the minimum spanning tree (MST) of such a graph with 11 nodes?
- (a)1 / 11 ( 11 n2 - 5n )
- (b)n2 - n + 1
- (c)6n – 11
- (d)2n + 1
An undirected graph G(V, E) contains n (n > 2) nodes named v1, v2, . . . , vn. Two nodes vi, vj are connected if and only if 0 < |i - j| ≤ 2. Each edge (vi, vj) is assigned a weight i + j. A sample graph with n = 4 is shown below. The length of the path from v5 to v6 in the MST of previous question with n = 10 is
- (a)11
- (b)25
- (c)31
- (d)41
Consider a complete undirected graph with vertex
set {0, 1, 2, 3, 4}. Entry Wij in the matrix W below
is the weight of the edge {i, j}.
0
1
8
1 4
l1
0
12
4 9
W = ⎪8 12
0
7 3⎪
1
4
7
0 2
h4
9
3
2 0)
What is the minimum possible weight of a spanning
tree T in this graph such that vertex 0 is a leaf node
in the tree T?- (a)7
- (b)8
- (c)9
- (d)10
Consider the following graph: Which one of the following is NOT the sequence of edges added to the minimum spanning tree using Kruskal's algorithm?
- (a)(b,e) (e,f) (a,c) (b,c) (f,g) (c,d)
- (b)(b,e) (e,f) (a,c) (f,g) (b,c) (c,d)
- (c)(b,e) (a,c) (e,f) (b,c) (f,g) (c,d)
- (d)(b,e) (e,f) (b,c) (a,c) (f,g) (c,d) ALGORITHMS Check Out Our Gate Courses & Secure Your Dream Rank !
For the undirected, weighted graph given below, which of the following sequences of edges represents a correct execution of Prim's algorithm to construct a Minimum Spanning Tree?
- (a)(a, b), (d, f), (f, c), (g, i), (d, a), (g, h), (c, e), (f, h)
- (b)(c, e), (c, f), (f, d), (d, a), (a, b), (g, h), (h, f), (g, i)
- (c)(d, f), (f, c), (d, a), (a, b), (c, e), (f, h), (g, h), (g, i)
- (d)(h, g), (g, i), (h, f), (f, c), (f, d), (d, a), (a, b), (c, e)
Consider the following graph: Which one of the following cannot be the sequence of edges added, in that order, to a minimum spanning tree using Kruskal's algorithm?
- (a)(a - b), (d - f), (b - f), (d - c), (d - e)
- (b)(a - b), (d - f), (d - c), (b - f), (d - e)
- (c)(d - f), (a - b), (d - c), (b - f), (d - e)
- (d)(d - f), (a - b), (b - f), (d - e), (d - c)
Self-check
Question 1
How many edges does Kruskal's algorithm accept for a connected graph with vertices?
Show answerHide
; all other edges are rejected as cycle-closing.
Question 2
What is the running time of Prim's algorithm with an adjacency matrix and no heap?
Show answerHide
.
Question 3
Why can union by rank keep trees of height at most ?
Show answerHide
A tree of rank has at least nodes (a tree only grows in rank when two trees of equal rank are joined), so .
Question 4
Do Kruskal's and Prim's algorithms always produce the same tree?
Show answerHide
Not with tied weights (there may be several minimum spanning trees); the total weight is always the same, and with distinct weights the tree is the same.
Revision card
One-screen revision
- Kruskal: sort + union-find, ; accepts edges in increasing weight order.
- Prim: keys and parents, array , heap , Fibonacci .
- Union by rank + path compression: per operation.
- Same weight always; same tree if weights distinct; dense: Prim, sparse: either.
References
- ·Cormen, Leiserson, Rivest, Stein, Introduction to Algorithms (3rd edition), Section 23.2 The algorithms of Kruskal and Prim; Chapter 21 Data Structures for Disjoint Sets
- ·Sedgewick and Wayne, Algorithms (4th edition), Section 4.3 Minimum Spanning Trees
- ·Dasgupta, Papadimitriou, Vazirani, Algorithms, Sections 5.1.3 and 5.1.4 (Kruskal, Prim) and 5.1.4 (union-find)
Verification
The C program on this page (Kruskal with union by rank and path compression, Prim with an array scan) gave the same total weight on the page graph (27) and on 2000 random connected graphs of 8 vertices with many tied weights; Kruskal and Prim were also compared with the exhaustive minimum over ALL spanning trees on 300 random graphs in an independent Python check, and union by rank kept every tree height at most log2 n on 300 random union sequences. The two animations are real runs of the code shown. The bounds for the Fibonacci heap and for the inverse Ackermann function are quoted from the textbook and were not tested. 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)