CO2 Topic 16 of 34
Prim's minimum spanning tree
Connect every vertex as cheaply as possible: grow one tree from a start vertex, always adding the cheapest edge that reaches a new vertex.
You will be able to
- Define a spanning tree and a minimum spanning tree (MST)
- State the cut property that makes greedy MST algorithms correct
- Trace Prim's algorithm and record the order in which edges are added
- Implement Prim with a priority queue and state its running time
Read
- Textbook 1, §23.1–23.2 Growing a minimum spanning tree; Prim's algorithm
- Textbook 2, §4.5 Minimum-cost spanning trees
- Textbook 3, §9.5 Minimum spanning tree
Watch
Intuition
A city must lay fibre cable so that every building is connected, digging as little as possible. The buildings are vertices, possible trenches are weighted edges. The cheapest way to connect everything is a minimum spanning tree (MST): a set of V − 1 edges that connects all vertices, has no cycle, and has the smallest total weight.
Prim's algorithm grows the network from one building: at every step, add the cheapest edge that connects the tree to a building not yet connected.
digraph {
node [shape=circle, fontname="Inter"]; edge [dir=none, fontname="JetBrains Mono"];
A -> B [label="4"]; A -> C [label="3", color="#14b8a6", penwidth=3]; B -> C [label="1", color="#14b8a6", penwidth=3];
B -> D [label="2", color="#14b8a6", penwidth=3]; C -> D [label="4"]; C -> E [label="5", color="#14b8a6", penwidth=3];
D -> E [label="7"]; D -> F [label="6"]; E -> F [label="2", color="#14b8a6", penwidth=3];
E -> G [label="3", color="#14b8a6", penwidth=3]; F -> G [label="4"];
}
The example graph; the thick teal edges form its MST (total weight 16).
How it works
Cut property (why greedy works): split the vertices into any two groups. The cheapest edge crossing between the groups belongs to some MST. Prim always takes the cheapest edge crossing between "in the tree" and "not yet in the tree", so every edge it adds is safe.
Trace from A:
| Step | Tree vertices | Cheapest crossing edge | Added weight |
|---|---|---|---|
| 1 | A | A–C (3) | 3 |
| 2 | A, C | C–B (1) | 1 |
| 3 | A, B, C | B–D (2) | 2 |
| 4 | A, B, C, D | C–E (5) — cheaper than D–F (6), D–E (7) | 5 |
| 5 | + E | E–F (2) | 2 |
| 6 | + F | E–G (3) — cheaper than F–G (4) | 3 |
Total weight 3 + 1 + 2 + 5 + 2 + 3 = 16, with 6 edges for 7 vertices.
Python implementation
import heapq
def prim(graph, start):
"""graph: {u: [(v, w), ...]} undirected. Returns (list of MST edges, total weight)."""
in_tree = {start}
heap = [(w, start, v) for v, w in graph[start]]
heapq.heapify(heap)
mst, total = [], 0
while heap and len(in_tree) < len(graph):
w, u, v = heapq.heappop(heap)
if v in in_tree:
continue # edge leads back into the tree: skip
in_tree.add(v)
mst.append((u, v, w))
total += w
for x, wx in graph[v]:
if x not in in_tree:
heapq.heappush(heap, (wx, v, x))
return mst, total
if __name__ == "__main__":
edges = [("A", "B", 4), ("A", "C", 3), ("B", "C", 1), ("B", "D", 2), ("C", "D", 4), ("C", "E", 5),
("D", "E", 7), ("D", "F", 6), ("E", "F", 2), ("E", "G", 3), ("F", "G", 4)]
g = {}
for u, v, w in edges:
g.setdefault(u, []).append((v, w))
g.setdefault(v, []).append((u, w))
mst, total = prim(g, "A")
print(mst) # [('A', 'C', 3), ('C', 'B', 1), ('B', 'D', 2), ('C', 'E', 5), ('E', 'F', 2), ('E', 'G', 3)]
print(total) # 16
Complexity
| Priority queue | Time | Best for |
|---|---|---|
| adjacency matrix + array scan | O(V²) | dense graphs |
| binary heap (as above) | O(E log V) | sparse graphs |
| Fibonacci heap | O(E + V log V) | theory |
An MST always has exactly V − 1 edges. If all edge weights are distinct, the MST is unique.
Common mistakes
- Adding an edge to a vertex already in the tree — that creates a cycle. Skip edges whose other end is already in the tree.
- Confusing Prim with Dijkstra. Prim compares single edge weights into the tree; Dijkstra compares total distances from the source. Their trees usually differ.
- Disconnected graphs. Prim only spans the start vertex's component; the result is a spanning forest only if you restart from each component.
- Thinking the MST gives shortest paths. The MST path between two vertices can be much longer than their shortest path.
Problems
- Run Prim on the example graph starting from G. Is the set of edges the same? The order?
- Lab: read a list of (village, village, cost) for possible roads and print the cheapest road network connecting all villages.
- Lab: implement the O(V²) array version of Prim for an adjacency matrix and compare its speed with the heap version on a dense graph.
- Prove that if all edge weights are distinct, the MST is unique. (Hint: cut property.)
- Give a graph where the MST path between two vertices is longer than their shortest path.
Quiz
GATE-style practice
Questions in the GATE CSE formats: MCQ (one correct option), MSQ (one or more correct options) and NAT (type a number). Each comes with a full worked solution. These are original practice questions, not past papers; for the real thing, see the official GATE site and its previous question papers.