Prim's algorithm is a greedy algorithm used to find a Minimum Spanning Tree (MST) of a connected, undirected, weighted graph.
It starts from one vertex and grows the MST one vertex at a time by choosing the cheapest edge that connects the current tree to a new vertex.
A priority queue or min-heap is commonly used to pick the next minimum edge efficiently.
Think of Prim's algorithm as building a network from one starting location. At every step, look at all cables leaving the already connected area and choose the cheapest cable that reaches a new location.
Prim's algorithm finds a minimum spanning tree of a weighted, undirected graph. A minimum spanning tree connects all vertices with the minimum possible total edge weight and contains no cycle.
Unlike Kruskal's algorithm, which sorts all edges globally, Prim's algorithm grows one connected tree. It begins from any vertex, then repeatedly selects the minimum-weight edge that goes from the current MST to a vertex not yet included.
| Term | Meaning |
|---|---|
| Spanning Tree | A tree that connects all vertices of a connected graph without cycles |
| Minimum Spanning Tree | A spanning tree with the smallest possible total edge weight |
| MST Set | The vertices already included in the growing MST |
| Key Value | The cheapest edge weight currently known for adding a vertex to the MST |
| Parent Array | Stores which vertex connects each selected vertex to the MST |
Prim is useful when we need to connect many points with minimum total cost and the graph is naturally represented by adjacency lists or adjacency matrices.
The algorithm keeps a growing tree and a record of the cheapest way to add every outside vertex.
Prim's algorithm is justified by the cut property of minimum spanning trees. At any point, the vertices already selected form one side of a cut, and the remaining vertices form the other side.
The lightest edge crossing this cut is safe to add to some MST. Prim repeatedly chooses exactly such an edge, so each greedy choice keeps the result optimal.
Consider a graph with 5 vertices: A, B, C, D, and E.
| Edge | Weight |
|---|---|
| A - B | 2 |
| A - D | 6 |
| B - C | 3 |
| B - D | 8 |
| B - E | 5 |
| C - E | 7 |
| D - E | 9 |
At each step, choose the smallest edge that connects the current MST to a new vertex.
| Step | MST Vertices Before Choice | Candidate Minimum Edge | Decision | MST Weight |
|---|---|---|---|---|
| 1 | {A} | A - B (2) | Add B through A-B | 2 |
| 2 | {A, B} | B - C (3) | Add C through B-C | 5 |
| 3 | {A, B, C} | B - E (5) | Add E through B-E | 10 |
| 4 | {A, B, C, E} | A - D (6) | Add D through A-D | 16 |
The graph has 5 vertices, so the MST must contain V - 1 = 4 edges.
A priority queue stores candidate edges or vertices ordered by smallest weight. This avoids scanning all edges manually at every step.
The Java program below stores graph edges in an adjacency list. Each priority queue item contains {weight, vertex, parent}.
import java.util.*;
public class PrimMST {
static class Edge {
int to;
int weight;
Edge(int to, int weight) {
this.to = to;
this.weight = weight;
}
}
static class Node {
int weight;
int vertex;
int parent;
Node(int weight, int vertex, int parent) {
this.weight = weight;
this.vertex = vertex;
this.parent = parent;
}
}
static int prim(List<Edge>[] graph, int start) {
int vertices = graph.length;
boolean[] inMST = new boolean[vertices];
PriorityQueue<Node> pq =
new PriorityQueue<>(Comparator.comparingInt(node -> node.weight));
pq.offer(new Node(0, start, -1));
int totalWeight = 0;
int selectedEdges = 0;
System.out.println("Edges in MST:");
while (!pq.isEmpty() && selectedEdges < vertices) {
Node current = pq.poll();
int u = current.vertex;
if (inMST[u]) {
continue;
}
inMST[u] = true;
totalWeight += current.weight;
selectedEdges++;
if (current.parent != -1) {
System.out.println(current.parent + " - " + u + " : " + current.weight);
}
for (Edge edge : graph[u]) {
if (!inMST[edge.to]) {
pq.offer(new Node(edge.weight, edge.to, u));
}
}
}
return totalWeight;
}
static void addEdge(List<Edge>[] graph, int u, int v, int weight) {
graph[u].add(new Edge(v, weight));
graph[v].add(new Edge(u, weight));
}
@SuppressWarnings("unchecked")
public static void main(String[] args) {
int vertices = 5;
List<Edge>[] graph = new ArrayList[vertices];
for (int i = 0; i < vertices; i++) {
graph[i] = new ArrayList<>();
}
addEdge(graph, 0, 1, 2); // A-B
addEdge(graph, 0, 3, 6); // A-D
addEdge(graph, 1, 2, 3); // B-C
addEdge(graph, 1, 3, 8); // B-D
addEdge(graph, 1, 4, 5); // B-E
addEdge(graph, 2, 4, 7); // C-E
addEdge(graph, 3, 4, 9); // D-E
int mstWeight = prim(graph, 0);
System.out.println("Total MST Weight = " + mstWeight);
}
}
Edges in MST:
0 - 1 : 2
1 - 2 : 3
1 - 4 : 5
0 - 3 : 6
Total MST Weight = 16
Many textbooks explain Prim using three arrays: key, parent, and mstSet. This version is useful for understanding the logic even if the priority queue version is faster for large sparse graphs.
| Array | Purpose |
|---|---|
| key[v] | Smallest known edge weight for connecting v to the MST |
| parent[v] | Vertex that connects v to the MST |
| mstSet[v] | Whether v is already included in the MST |
Let V be the number of vertices and E be the number of edges.
| Implementation | Time Complexity | Space Complexity | Best Use |
|---|---|---|---|
| Adjacency matrix without heap | O(V^2) | O(V^2) | Dense graphs or classroom explanation |
| Adjacency list with binary heap | O((V + E) log V) | O(V + E) | Sparse graphs and practical code |
| Adjacency list with Fibonacci heap | O(E + V log V) | O(V + E) | Theoretical optimization |
| Point | Prim | Kruskal |
|---|---|---|
| Strategy | Grow one connected tree | Pick globally lightest safe edges |
| Main input style | Adjacency list or matrix | Edge list |
| Main data structure | Priority queue or key array | Union-Find |
| Cycle handling | Avoids cycles by adding only outside vertices | Checks cycles using DSU |
| Often preferred for | Dense graphs | Sparse graphs |
Use Prim to find shortest paths from one source.
Use Prim to find a minimum spanning tree.
Choose the smallest edge in the whole graph at every step.
Choose the smallest edge that connects the current MST to a new vertex.
Allow a selected vertex to be added again from the priority queue.
Skip vertices that are already marked inMST.
Yes. At each step, it greedily chooses the cheapest edge that connects the current MST to a new vertex.
Yes. Prim can start from any vertex in a connected graph. The order of selected edges may differ, but the total MST weight remains minimum.
Yes. MST algorithms can handle negative edge weights because they compare edge weights directly and do not depend on path distance relaxation.
Prim chooses the cheapest edge to expand the MST. Dijkstra chooses the vertex with the smallest total distance from the source. Their priority queues look similar, but their goals are different.
A single MST cannot be formed. You can run Prim separately on each component to get a minimum spanning forest.
Explore 500+ free tutorials across 20+ languages and frameworks.