← SciSim / Computer Science

△ Prim's MST Algorithm

Minimum Spanning Tree | Grow from Vertex | Priority Queue | O(E log V)

Standard Undergraduate

§1 — Interactive Simulation

Ready. Press Play or Next to begin.
Speed:
0
Operations
0
Comparisons
0/0
Step
n / size
PRIM(G, start):
  key[start]=0; key[v]=INF for all v!=start
  inMST[v]=false for all v
  PQ = min-priority-queue with all vertices
  while PQ not empty:
    u = PQ.extract_min() // minimum key vertex
    inMST[u] = true
    for each neighbor v of u with edge weight w:
      if not inMST[v] and w < key[v]:
        key[v]=w; parent[v]=u; PQ.decrease_key(v,w)

§2 — The Idea, Step by Step

Start here (middle school). Imagine wiring up a new neighborhood. One house already has power, and you must connect every other house using the least total cable. The natural move: look at all the houses already connected, find the single cheapest wire that reaches a brand-new house, lay it, and repeat. You never design the whole network at once — you just keep grabbing the cheapest wire that grows your connected cluster by one house. That is Prim's algorithm.
Name the pieces (high school). A network is a graph of $V$ vertices (houses) joined by weighted edges (cables of cost $w$). Prim's keeps a growing tree of connected vertices and, for every vertex $v$ still outside, a number $key[v]$ = the cheapest single edge that would attach $v$ to the current tree. Each round you pick the outside vertex with the smallest $key$, pull it in, and refresh its neighbors' keys.
One worked example. Start at A with edges A–B $= 4$, A–C $= 1$, B–C $= 2$. The cheapest edge leaving A is A–C $= 1$, so C joins first. Now B can attach through A–B $= 4$ or the cheaper C–B $= 2$, so $key[B]$ drops to $2$. Add B–C $= 2$. Total cost $= 1 + 2 = 3$, using exactly $V-1 = 2$ edges — the minimum spanning tree.
Why it is correct (AP / college). At every step the connected set and the outside set form a cut. The minimum-weight edge crossing any cut is always safe to add to some MST — the Cut Property. Prim's smallest-$key$ pick is exactly that minimum crossing edge, so it never errs. The update rule applied to each neighbor whenever a new vertex $u$ joins is $$key[v] \leftarrow \min\bigl(key[v],\; w(u,v)\bigr).$$ With a binary-heap priority queue the cost is $O((V+E)\log V) = O(E\log V)$; with a plain array scan it is $O(V^2)$, which actually wins on dense graphs where $E \approx V^2$.
Try this in the panel above. (1) Drag the $n$ slider from small to large and watch the Comparisons counter climb — that super-linear growth is the same scaling that separates $O(V^2)$ from $O(E\log V)$. (2) Switch between the Sorted and Reverse presets to compare best- and worst-case operation counts. (3) Tap ▶│ to advance one move at a time and watch a greedy method commit to a single cheapest choice each round — exactly how Prim's commits to one cheapest edge per step.

§3 — Algorithm Analysis & Derivation

SymbolMeaning
nInput size (vertices V, edges E, or array length)
T(n)Time complexity function
W(n)Worst-case complexity
A(n)Average-case complexity
hHeight or depth of structure
kNumber of distinct values / items
Step 1 -- Grow from a Seed. Prim's grows the MST one vertex at a time from a starting vertex. key[v] = minimum weight edge connecting v to the current MST. Always add the vertex with smallest key (minimum cut edge).
Step 2 -- Correctness via Cut Property. At each step, the current MST tree defines a cut (MST vertices vs non-MST vertices). The vertex with minimum key represents the minimum weight edge crossing this cut. By the Cut Property, this edge is in some MST.
Step 3 -- Time with Binary Heap. V extract-min: O(V log V). E decrease-key: O(E log V). Total: O((V+E) log V) = O(E log V) for connected graphs.
Step 4 -- Time with Simple Array. Find min-key vertex by scanning all V vertices: O(V). Done V times: O(V^2). Update keys: O(E). Total: O(V^2). Better than heap for dense graphs (E = O(V^2)).
Step 5 -- vs Kruskal. Prim: starts from a vertex, grows tree greedily. Better for dense graphs with adjacency matrix O(V^2). Kruskal: sorts all edges globally. Better for sparse graphs O(E log E). Both give valid MST.
Step 6 -- MST Weight Recovery. Sum of all key[] values (after algorithm) = total MST weight. Or sum edge weights as they are added. MST edges: (parent[v], v) for all v != start.

§4 — Frequently Asked Questions

How is Prim's similar to Dijkstra? concept+
Both use a greedy priority queue strategy. Key difference: Dijkstra's key[v] = total distance from source (path weight). Prim's key[v] = minimum SINGLE edge weight connecting v to current MST. Dijkstra finds shortest paths; Prim finds MST.
Can Prim's algorithm start from any vertex? concept+
Yes -- the MST (or MST weight) is the same regardless of starting vertex, assuming the graph is connected. Different starting vertices give different orderings of edge additions but the same MST (if edge weights are unique).
Why is Prim's O(V^2) better for dense graphs? applied+
Dense graph: E ~ V^2 edges. Prim with array: O(V^2). Prim with heap: O(E log V) = O(V^2 log V). Array wins. Dense graphs arise in complete graphs, fully connected networks, all-pairs problems. Sparse graphs (road networks, social networks) favor heap Prim or Kruskal.
What is lazy Prim's algorithm? nonobv+
Lazy Prim: push all edges from newly added vertices into PQ without decrease-key. Multiple entries for same vertex. Pop minimum; if vertex already in MST, skip. Simpler to implement but PQ grows to O(E) size. Time: O(E log E). Used when decrease-key is hard to implement (Java PriorityQueue).
How does Prim's handle disconnected graphs? applied+
Prim from a single start vertex only reaches vertices in the same connected component. For disconnected graphs, run Prim from one unvisited vertex per component. Result: Minimum Spanning Forest.
What is the relationship between MST and network design? deep+
MST minimizes total cable length to connect n cities. But MST assumes all cities must be connected. Steiner tree problem: connect a subset of vertices with minimum total edge weight (allowing additional Steiner points). Steiner tree is NP-hard in general; MST provides a 2-approximation for the special case of connecting all terminals.

§5 — Common Misconceptions & Errors

Conceptual Misconceptions

✗ Prim's and Dijkstra's are the same algorithm.

✓ Both use greedy PQ, but key[] means different things. Prim: key[v] = min edge weight to MST. Dijkstra: key[v] = total path distance from source. Same structure, different semantics and different outputs.

✗ Prim's only works on undirected graphs.

✓ Prim's MST is defined for undirected graphs. For directed graphs, the analogous problem (Minimum Spanning Arborescence) requires Edmonds' algorithm.

✗ The starting vertex affects the MST weight.

✓ MST total weight is invariant of starting vertex (for unique edge weights). Starting vertex only affects the ORDER in which edges/vertices are added.

Implementation Errors

✗ Using Prim's without a priority queue is always slower.

✓ For dense graphs (E=O(V^2)), simple array scan O(V^2) beats heap O(V^2 log V). For sparse graphs, heap wins.

✗ Forgetting to check inMST[v] before updating key.

✓ Without the inMST check, you may try to update a vertex already in the MST -- wasted operations or incorrect behavior if using indexed PQ.

✗ Using parent[start] as a valid MST edge.

✓ parent[start] is undefined (start has no parent). The MST has V-1 edges: parent[v] for all v != start.