Week 13, Wednesday — Prim’s Algorithm
April 2, 2026
Adjacency list (you’ve seen this)
Space: \(O(V + E)\)
Iterate neighbors of \(v\): \(O(\deg(v))\)
Check if edge \((u,v)\) exists: \(O(\deg(u))\)
Adjacency matrix (new today)
| A | B | C | D | E | F | |
|---|---|---|---|---|---|---|
| A | – | 8 | 2 | 4 | – | – |
| B | 8 | – | 7 | – | 2 | – |
| C | 2 | 7 | – | 1 | 3 | 9 |
| D | 4 | – | 1 | – | – | 5 |
| E | – | 2 | 3 | – | – | – |
| F | – | – | 9 | 5 | – | – |
Space: \(O(V^2)\)
Iterate neighbors of \(v\): \(O(V)\)
Check if edge \((u,v)\) exists: \(O(1)\)

You can pave road segments. Each segment costs its number of paving stones.
Goal: pave the __________ stones so every house can reach every other.
Which roads do you pave?
How many stones total?
Input: connected, undirected graph \(G\) with edge weights
Output: subgraph \(G'\) such that:
What is the MST of this graph?
Total weight = ____
What’s true about every cycle in this graph?
Theorem: ___________________________________
Proof: ______________________________________
Edge C–F is not in the MST. Using the theorem you just derived — what is the minimum possible weight for C–F?
MST path C → F: _________________
Min weight of C–F: _____
Theorem: ___________________________________
(for any non-MST edge)
MST minimizes total edge weight — the cost of connecting everything.
Shortest path minimizes the distance between two specific nodes.
These are different objectives.
Partition Property (Cut Property)
Split vertices into any two sets \(S\) and \(V \setminus S\).
The minimum-weight edge crossing the cut is always in some MST.
MST total weight = ____
What type is graph? What type is graph[v]?
Running time? (in terms of \(|V|\) and \(|E|\))
graph |
neighbors |
|---|---|
A |
B, D, E |
B |
A, E, C |
C |
B, D |
D |
A, C |
E |
A, B |
The bag determines what the algorithm optimizes:
| Bag | Explores by | Algorithm |
|---|---|---|
| Queue (FIFO) | distance from source (hops) | BFS |
| Priority queue (min edge weight) | cheapest edge to tree | Prim’s MST |
| Priority queue (min total distance) | shortest path from source | Dijkstra’s SSSP |
One change turns BFS into Prim’s:
Replace the queue with a Priority Queue keyed by edge weight. Instead of “which node did I discover first?”, ask “which unvisited node is cheapest to connect to the tree?”
Initialize: for each v: d[v] ← ∞, p[v] ← null d[s] ← 0 Q ← min-PQ of all vertices, keyed by d
while Q not empty:
v ← Q.removeMin()
for each neighbor w of v:
if w ∈ Q and cost(v,w) < d[w]:
d[w] ← cost(v,w)
p[w] ← v
Q.decreaseKey(w, d[w])
return p
Initialize: for each v: d[v] ← ∞, p[v] ← null d[s] ← 0 Q ← min-PQ of all vertices, keyed by d
while Q not empty:
v ← Q.removeMin()
for each neighbor w of v:
if w ∈ Q and cost(v,w) < d[w]:
d[w] ← cost(v,w)
p[w] ← v
Q.decreaseKey(w, d[w])
return p
What design choices do we need to make?
Put a ⭐ by __________________ operations.
Put a 💜 by __________________ operations.
Initialize: for each v: d[v] ← ∞, p[v] ← null d[s] ← 0 Q ← min-PQ of all vertices, keyed by d
while Q not empty:
v ← Q.removeMin() ⭐
for each neighbor w of v: 💜
if w ∈ Q and cost(v,w) < d[w]:
d[w] ← cost(v,w)
p[w] ← v
Q.decreaseKey(w, d[w]) ⭐
return p
⭐ \(n\) removeMins + \(\leq m\) decreaseKeys
💜 \(O(m)\) total (adj list) | \(O(n^2)\) total (adj matrix)
| Adj matrix | Adj list | |
|---|---|---|
| heap | \(O(n^2 + m \log n)\) | \(O(m \log n)\) |
| unsorted array | \(O(n^2)\) | \(O(n^2)\) |
Which is best? Depends on graph density:
import heapq
def prim(graph, start):
"""graph: {vertex: [(neighbor, weight), ...]}"""
d = {v: float('inf') for v in graph} # cheapest edge to reach v
parent = {v: None for v in graph}
d[start] = 0
pq = [(0, start)] # (edge_weight, vertex)
visited = set()
while pq:
cost, v = heapq.heappop(pq)
if v in visited:
continue
visited.add(v)
for w, weight in graph[v]:
if w not in visited and weight < d[w]:
d[w] = weight # just the edge weight (not cumulative!)
parent[w] = v
heapq.heappush(pq, (weight, w))
return parent # MST as parent pointers