Prim’s Algorithm
Prim’s algorithm (1957) takes a different angle: instead of sorting all edges globally, it grows the MST one vertex at a time from an arbitrary starting node. At each step it asks: “what’s the cheapest edge connecting the current tree to a vertex not yet in the tree?”
This is also justified by the cut property: at every step, S = the set of vertices already in the tree and V − S = the rest. Prim’s always picks the minimum crossing edge — the cut property guarantees this is the right move.
The algorithm
Initialize
Mark all vertices as “not in tree.” Put the start vertex in the tree with cost 0. Push all edges of the start vertex into a min-heap (priority queue keyed by edge weight).
Greedy extension loop
While the tree has fewer than n vertices:
- Pop the cheapest edge (w, u, v) from the heap.
- If v is already in the tree — skip (this edge would create a cycle).
- Otherwise, add v to the tree. Record w as v’s “key” (its contribution to the MST cost). Push all edges of v into the heap.
Done
When n vertices are in the tree, the MST is complete.
Worked example
Same graph as before. Starting from vertex A.
| Step | Heap top | Action | Tree |
|---|---|---|---|
| Init | — | Add A, push A’s edges: (4,A→B), (2,A→C) | A |
| 1 | (2, A→C) | Add C, push C’s edges: (1,C→B), (8,C→E) | A, C |
| 2 | (1, C→B) | Add B, push B’s edges: (5,B→D) | A, C, B |
| 3 | (4, A→B) | B already in tree — skip | A, C, B |
| 4 | (5, B→D) | Add D, push D’s edges: (2,D→E), (6,D→F) | A, C, B, D |
| 5 | (2, D→E) | Add E, push E’s edges: (3,E→F) | A, C, B, D, E |
| 6 | (3, E→F) | Add F | A, C, B, D, E, F |
MST edges: A-C(2), C-B(1), B-D(5), D-E(2), E-F(3). Total: 13. Same MST as Kruskal’s.
Implementation — lazy Prim’s (heap of edges)
The “lazy” variant pushes all edges of a newly added vertex into the heap without removing stale entries. Stale entries (edges to already-added vertices) are detected and skipped when popped.
Eager Prim’s — fewer heap entries
The lazy version may put O(E) entries in the heap. The “eager” variant maintains, for each unvisited vertex v, only the current best edge connecting it to the tree. When a shorter edge is found, it decreases the key in the heap (a “decrease-key” operation).
With a Fibonacci heap, eager Prim’s runs in O(E + V log V). With a standard binary heap, decrease-key is O(log V) per update, giving O(E log V) — same asymptotic as the lazy version but with a smaller heap.
For competitive programming and interviews, lazy Prim’s is almost always sufficient. Implement eager only if explicitly asked for the Fibonacci-heap version.
Dense-graph Prim’s: O(V²) with an array
For dense graphs (E ≈ V²), using an adjacency matrix and scanning all vertices instead of a heap gives O(V²) — better than O(E log E) = O(V² log V).
def prim_dense(n, dist_matrix):
# dist_matrix[i][j] = edge weight, float('inf') if no edge
key = [float('inf')] * n
in_tree = [False] * n
key[0] = 0
total = 0
for _ in range(n):
# Find the unvisited vertex with the smallest key
u = min((i for i in range(n) if not in_tree[i]), key=lambda i: key[i])
in_tree[u] = True
total += key[u]
for v in range(n):
if not in_tree[v] and dist_matrix[u][v] < key[v]:
key[v] = dist_matrix[u][v]
return totalThis O(V²) version is the right choice for:
- Complete graphs (every pair of vertices connected)
- Min Cost to Connect All Points (LC 1584), where the graph is implicitly complete
Kruskal’s vs Prim’s
| Property | Kruskal’s | Prim’s (lazy) |
|---|---|---|
| Approach | Global edge sort + union-find | Local greedy growth from one vertex |
| Time (sparse) | O(E log E) | O(E log V) |
| Time (dense) | O(E log E) = O(V² log V) | O(V²) with array |
| Data structure | Union-Find | Priority queue |
| Handles disconnected graphs | Yes (spanning forest) | No (stays in one component) |
| Implementation | Often shorter | More intuitive for some |
| Best for | Sparse graphs, edge-list input | Dense graphs, adjacency matrix |
In practice, for most interview problems (sparse graphs, edge list given): use Kruskal’s. For geometric problems where every pair of points is connected (like Min Cost to Connect All Points): use Prim’s dense variant with O(V²), which avoids explicitly creating all O(V²) edges.
Quick check
Next: Advanced Patterns — Borůvka’s algorithm, minimum bottleneck spanning trees, second-best MST, and real-world MST applications.