G27
Self-checkedTier 1 14 min readalgo.mst-kruskal-prim

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 nn elements into sets and supports make-set, find(x)(x) (the representative of the set containing xx) and union(a,b)(a, b) (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 log⁡2n\log_2 n; path compression (in find, point every node on the path directly at the root) flattens the trees. With both, a sequence of mm operations on nn elements takes O(m α(n))O(m\,\alpha(n)) time, where α\alpha is the inverse Ackermann function, below 55 for every practical nn: effectively constant.

Kruskal's algorithm. Sort the edges by weight. Make each vertex a set. For each edge (u,v)(u, v) in order: if find(u)≠find(v)\text{find}(u) \ne \text{find}(v), add the edge to the tree and union the two sets; otherwise skip it (it would close a cycle). Stop after V−1V - 1 edges.

Prim's algorithm. Pick a root. Keep for every vertex vv outside the tree a key[v]\text{key}[v]: the weight of the cheapest edge joining vv to the tree (infinity if none), and parent[v]\text{parent}[v] the tree end of that edge. Repeatedly take the vertex uu outside the tree with the smallest key, add it (and the edge to its parent) to the tree, and for each neighbour vv outside the tree with w(u,v)<key[v]w(u, v) < \text{key}[v] set key[v]=w(u,v)\text{key}[v] = w(u, v) and parent[v]=u\text{parent}[v] = u.

How it works

Kruskal, step by step

The graph has 77 vertices and 1111 edges, listed here in order of weight: (1,2)=2(1,2)=2, (3,4)=3(3,4)=3, (0,1)=4(0,1)=4, (4,5)=5(4,5)=5, (2,3)=6(2,3)=6, (5,6)=7(5,6)=7, (1,3)=8(1,3)=8, (0,2)=9(0,2)=9, (2,4)=10(2,4)=10, (4,6)=11(4,6)=11, (3,5)=12(3,5)=12. 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 run

C source

1#include <stdio.h>
2
3#define N 7
4
5struct edge {
6 int u, v, w;
7};
8
9static int parent_[N], rank_[N];
10
11static int find(int x) {
12 if (parent_[x] != x) {
13 parent_[x] = find(parent_[x]); /* path compression */
14 }
15 return parent_[x];
16}
17
18/* joins the sets of a and b; returns 0 if they were already one set */
19static int unite(int a, int b) {
20 int ra = find(a), rb = find(b);
21 if (ra == rb) {
22 return 0;
23 }
24 if (rank_[ra] < rank_[rb]) {
25 int t = ra;
26 ra = rb;
27 rb = t;
28 }
29 parent_[rb] = ra; /* union by rank */
30 if (rank_[ra] == rank_[rb]) {
31 rank_[ra]++;
32 }
33 return 1;
34}
35
36/* the edges e[0..m-1] are sorted by weight; chosen[i] is set to 1 or 0; returns the weight of the tree */
37int kruskal(const struct edge e[], int m, int chosen[]) {
38 int total = 0;
39 for (int v = 0; v < N; v++) {
40 parent_[v] = v;
41 rank_[v] = 0;
42 }
43 for (int i = 0; i < m; i++) {
44 if (unite(e[i].u, e[i].v)) {
45 chosen[i] = 1;
46 total += e[i].w;
47 } else {
48 chosen[i] = 0;
49 }
50 }
51 return total;
52}

chosen (1 = in the tree, 0 = rejected, blank = not yet looked at)

0
1
2
3
4
5
6
7
8
9
10

weight of edge i (the edges are sorted by weight)

2
0
3
1
4
2
5
3
6
4
7
5
8
6
9
7
10
8
11
9
12
10

one end of edge i

1
0
3
1
0
2
4
3
2
4
5
5
1
6
0
7
2
8
4
9
3
10

other end of edge i

2
0
4
1
1
2
5
3
3
4
6
5
3
6
2
7
4
8
6
9
5
10

the set (tree) of each vertex = its root in the union-find forest

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

State

edges accepted = 0 of 6 needed, total weight so far = 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 graph with 7 vertices and 11 edges, listed in order of increasing weight. Find a minimum spanning tree.

1 / 14
The 7-vertex weighted graph with 11 edges (already sorted by weight) is set up by hidden driver code. kruskal() with its union-find functions is the exact code that runs; the component labels in the picture are the roots found by the real find(). 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 first six edges are accepted (each joins two different trees); after the sixth, edge (5,6)(5, 6) with weight 77, there is one tree of 66 edges and weight 2727, and the remaining five edges all have both ends in the same tree and are rejected. A spanning tree of 77 vertices has exactly 66 edges, so the algorithm can stop as soon as it has accepted V−1V - 1 edges.

Correctness. When Kruskal accepts (u,v)(u, v), uu and vv are in different trees TuT_u and TvT_v of the current forest. Take the cut (V(Tu),rest)(V(T_u), \text{rest}): it respects the chosen edges, and the edge (u,v)(u, v) crosses it. Every edge lighter than (u,v)(u, v) 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 (u,v)(u, v) is the lightest crossing edge, i.e. light, hence safe by the cut property.

Running time. Sorting: O(Elog⁡E)O(E \log E). The loop: EE find operations and at most V−1V - 1 unions: O(E α(V))O(E\,\alpha(V)), which is dominated by the sort. Since E≤V2E \le V^2 we have log⁡E≤2log⁡V\log E \le 2 \log V, so O(Elog⁡E)=O(Elog⁡V)O(E \log E) = O(E \log V). 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 00. 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 run

C source

1#include <stdio.h>
2
3#define N 7
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 */
7static int in_tree[N];
8
9/* key[v] = weight of the cheapest edge joining v to the tree so far; parent[v] = the tree end of that edge */
10int prim(int root, int key[], int parent[]) {
11 int total = 0;
12 for (int v = 0; v < N; v++) {
13 key[v] = INF;
14 parent[v] = -1;
15 in_tree[v] = 0;
16 }
17 key[root] = 0;
18 for (int round = 0; round < N; round++) {
19 int u = -1;
20 for (int v = 0; v < N; v++) {
21 if (!in_tree[v] && (u == -1 || key[v] < key[u])) {
22 u = v;
23 }
24 }
25 in_tree[u] = 1;
26 total += key[u];
27 for (int v = 0; v < N; v++) {
28 if (w[u][v] != 0 && !in_tree[v] && w[u][v] < key[v]) {
29 key[v] = w[u][v];
30 parent[v] = u;
31 }
32 }
33 }
34 return total;
35}

in the tree (1 = yes)

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

key[v] (blank = infinity)

0
1
2
3
4
5
6

parent[v]

0
1
2
3
4
5
6

State

vertices in the tree = 0 of 7, total weight so far = 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

The same weighted graph. Prim's algorithm grows ONE tree from vertex 0.

1 / 21
The same weighted graph as Kruskal's animation, as a weight matrix (0 = no edge), is set up by hidden driver code. prim() 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

Vertex 00 joins with key 00; its neighbours 11 and 22 get keys 44 and 99. The cheapest outside vertex is 11 (key 44); that lowers the key of 22 to 22 (via the edge (1,2)(1, 2)) and gives 33 the key 88. Then 22 (key 22), which lowers the key of 33 to 66; then 33 (key 66), then 44 (key 33), 55 (key 55) and 66 (key 77): total 4+2+6+3+5+7=274 + 2 + 6 + 3 + 5 + 7 = 27. 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 (tree,rest)(\text{tree}, \text{rest}) 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 keyTime
unsorted array (scan all vertices each round), adjacency matrixΘ(V2)\Theta(V^2)
binary min-heap, adjacency listsO((V+E)log⁡V)=O(Elog⁡V)O((V + E) \log V) = O(E \log V) for a connected graph
Fibonacci heapO(E+Vlog⁡V)O(E + V \log V)

With a heap, each vertex is extracted once (VV extractions of O(log⁡V)O(\log V)) and each edge may lower a key once (EE decrease-key operations of O(log⁡V)O(\log V) in a binary heap).

Which to use

  • Sparse graph (EE about VV): both are O(Vlog⁡V)O(V \log V); Kruskal is simplest if the edges come as a list.
  • Dense graph (EE about V2V^2): Prim with an array and a matrix, O(V2)O(V^2), beats Kruskal's O(V2log⁡V)O(V^2 \log V).
  • 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 20002000 random connected graphs with 88 vertices and random weights from 11 to 2020 (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
inputKruskal weightPrim weightresult
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.

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

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

Easy

Edges: AB=1AB = 1, BC=4BC = 4, AC=3AC = 3, CD=2CD = 2, BD=5BD = 5. Sorted: AB 1AB\,1, CD 2CD\,2, AC 3AC\,3, BC 4BC\,4, BD 5BD\,5. Take ABAB (joins {A}\{A\}, {B}\{B\}). Take CDCD (joins {C}\{C\}, {D}\{D\}). Take ACAC (joins {A,B}\{A, B\} and {C,D}\{C, D\}). Three edges for 44 vertices: done. Weight 1+2+3=61 + 2 + 3 = 6. The edges BCBC and BDBD would not even be looked at if we stop at V−1V - 1 edges; they would have been rejected (cycles).

EX 2Prim on the same graph from A

Easy

Keys: B=1B = 1, C=3C = 3, D=∞D = \infty. Take BB (key 11): CC: min⁡(3,4)=3\min(3, 4) = 3, DD: 55. Take CC (key 33): DD: min⁡(5,2)=2\min(5, 2) = 2. Take DD (key 22). Weight 1+3+2=61 + 3 + 2 = 6, the same tree AB,AC,CDAB, AC, CD. Order of addition: B,C,DB, C, D.

EX 3Union-find by hand

Medium

Elements 0,…,50, \ldots, 5, each its own set. union(0,1)\text{union}(0, 1): roots 00 and 11, equal rank 00: attach 11 below 00 and rank of 00 becomes 11. union(2,3)\text{union}(2, 3): 33 below 22. union(0,2)\text{union}(0, 2): ranks 11 and 11 are equal: attach 22 below 00, rank 22. find(3)\text{find}(3) walks 3→2→03 \to 2 \to 0 and with path compression makes 33 point to 00 directly. The height never exceeds log⁡26≈2.6\log_2 6 \approx 2.6.

EX 4When ties matter

Medium

A triangle with all three edges of weight 11: 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 33 MSTs, all of weight 22. 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 EE edges and VV vertices: O(Elog⁡E)O(E \log E), i.e. O(Elog⁡V)O(E \log V). (b) Prim with an adjacency matrix and an array: O(V2)O(V^2). (c) Prim with a binary heap: O(Elog⁡V)O(E \log V). (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 EE, 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, O(V2)O(V^2).

Cheat box

Cheat box

  • Kruskal: sort edges; add an edge iff its ends are in different sets (union-find); stop at V−1V - 1 edges. O(Elog⁡E)=O(Elog⁡V)O(E \log E) = O(E \log V).
  • Prim: grow one tree; key[v] = cheapest edge to the tree; take the smallest key. Array/matrix O(V2)O(V^2); binary heap O(Elog⁡V)O(E \log V); Fibonacci heap O(E+Vlog⁡V)O(E + V \log V).
  • Both correct by the cut property; same total weight; trees can differ under ties.
  • Union-find: union by rank (height ≤log⁡2n\le \log_2 n) + path compression: O(α(n))O(\alpha(n)) 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

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

GATE 2024 · Set 2 · NATQ10 · page 114 of the book
The number of distinct minimum-weight spanning
trees of the following graph is
.
GATE 2020 · NAT · 2 marksQ18 · page 115 of the book
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 !
5
GATE 2015 · Set 1 · NAT · 2 marksQ26 · page 117 of the book
The 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 is
year not read yetQ31 · page 118 of the book
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.

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
GATE 2011 · MCQ · 2 marksQ32 · page 118 of the book
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
GATE 2010 · MCQ · 2 marksQ33 · page 118 of the book
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
GATE 2009 · MCQ · 2 marksQ34 · page 118 of the book
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 !
GATE 2008 · MCQ · 2 marksQ36 · page 119 of the book
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)
GATE 2006 · MCQ · 1 markQ43 · page 120 of the book
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 99 vertices?

Show answer

88; 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 answer

O(V2)O(V^2).

Question 3

Why can union by rank keep trees of height at most log⁡2n\log_2 n?

Show answer

A tree of rank rr has at least 2r2^r nodes (a tree only grows in rank when two trees of equal rank are joined), so r≤log⁡2nr \le \log_2 n.

Question 4

Do Kruskal's and Prim's algorithms always produce the same tree?

Show answer

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, O(Elog⁡V)O(E \log V); accepts V−1V - 1 edges in increasing weight order.
  • Prim: keys and parents, array O(V2)O(V^2), heap O(Elog⁡V)O(E \log V), Fibonacci O(E+Vlog⁡V)O(E + V \log V).
  • Union by rank + path compression: α(n)\alpha(n) 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