Minimum Spanning Tree Prim's Algorithm in DSA Rust - Time & Space Complexity
We want to understand how the time needed to find the minimum spanning tree using Prim's algorithm changes as the graph grows.
How does the algorithm's work increase when we add more nodes and edges?
Analyze the time complexity of the following code snippet.
fn prim_mst(graph: &Vec>) -> i32 {
let n = graph.len();
let mut visited = vec![false; n];
let mut min_heap = std::collections::BinaryHeap::new();
min_heap.push((0, 0));
let mut total_cost = 0;
while let Some((cost, u)) = min_heap.pop() {
if visited[u] { continue; }
visited[u] = true;
total_cost += -cost;
for &(v, w) in &graph[u] {
if !visited[v] {
min_heap.push((-w, v));
}
}
}
total_cost
}
This code finds the minimum spanning tree cost of a graph using Prim's algorithm with a priority queue.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop runs until all nodes are visited, and inside it, edges connected to the current node are checked.
- How many times: The loop runs up to n times for nodes, and the inner for-loop runs for all edges connected to those nodes, totaling m edges.
As the number of nodes (n) and edges (m) increase, the algorithm processes each edge and node to build the tree.
| Input Size (n, m) | Approx. Operations |
|---|---|
| 10 nodes, 15 edges | About 10 pops and 15 edge checks |
| 100 nodes, 200 edges | About 100 pops and 200 edge checks |
| 1000 nodes, 5000 edges | About 1000 pops and 5000 edge checks |
Pattern observation: The work grows roughly with the number of nodes plus edges, so more nodes and edges mean more operations.
Time Complexity: O((n + m) log n)
This means the time grows with the number of nodes and edges, multiplied by the cost of managing the priority queue.
[X] Wrong: "Prim's algorithm always runs in simple linear time O(n)."
[OK] Correct: The algorithm uses a priority queue that requires extra time to add and remove edges, so the log factor from the queue operations matters.
Understanding this time complexity helps you explain how efficient your solution is when working with graphs, a common topic in interviews.
"What if we used a simple array instead of a priority queue to pick the next edge? How would the time complexity change?"
Practice
Solution
Step 1: Understand Prim's Algorithm purpose
Prim's Algorithm builds a tree that connects all vertices with the smallest possible sum of edge weights.Step 2: Compare with other graph algorithms
Shortest path algorithms find paths, cycle detection finds loops, and topological sort orders vertices, which are different goals.Final Answer:
To find the minimum spanning tree connecting all vertices with minimum total edge weight -> Option BQuick Check:
Prim's Algorithm = Minimum Spanning Tree [OK]
- Confusing Prim's with shortest path algorithms
- Thinking it detects cycles
- Mixing it with topological sorting
Solution
Step 1: Identify operation needed in Prim's Algorithm
Prim's needs to repeatedly select the edge with the smallest weight efficiently.Step 2: Choose data structure for minimum extraction
A BinaryHeap (min-heap) allows quick access to the smallest element, unlike Vec or LinkedList which require scanning.Final Answer:
BinaryHeap (Min-Heap) -> Option DQuick Check:
Min-Heap = Efficient minimum edge selection [OK]
- Using Vec which is slow for minimum extraction
- Choosing HashMap which is for key-value, not min extraction
- Using LinkedList which is inefficient for this
let edges = vec![(0,1,2), (1,2,3), (0,2,1)]; // Prim's MST total weight calculation // Output the total weight of MST
Solution
Step 1: List edges and weights
Edges: (0-1)=2, (1-2)=3, (0-2)=1. Start from vertex 0.Step 2: Build MST using Prim's Algorithm
Start at 0, pick smallest edge (0-2)=1, then pick next smallest connecting edge (0-1)=2. Total weight = 1 + 2 = 3.Step 3: Check if all vertices connected
Vertices 0,1,2 connected with edges (0-2) and (0-1). Edge (1-2) with weight 3 is not needed.Final Answer:
3 -> Option AQuick Check:
MST weight = 1 + 2 = 3 [OK]
- Adding all edges instead of MST edges
- Choosing heavier edges first
- Not starting from given start vertex
let mut visited = vec![false; n];
let mut heap = BinaryHeap::new();
heap.push(Reverse((0, 0)));
while let Some(Reverse((cost, u))) = heap.pop() {
if visited[u] { continue; }
visited[u] = true;
for &(v, w) in &graph[u] {
if !visited[v] {
heap.push(Reverse((w, v)));
}
}
}Solution
Step 1: Analyze visited check placement
Currently, neighbors are pushed without checking if visited, causing duplicates in heap.Step 2: Fix by checking visited before pushing neighbors
Adding a visited check before pushing neighbors avoids unnecessary heap entries and improves efficiency.Final Answer:
The visited check is missing before pushing neighbors -> Option CQuick Check:
Check visited before pushing neighbors to heap [OK]
- Ignoring visited check before pushing neighbors
- Confusing min-heap with max-heap
- Swapping vertex and weight in tuples
(0,1,10), (0,2,6), (0,3,5), (1,3,15), (2,3,4), (3,4,2)Using Prim's Algorithm starting from vertex 0, what is the total weight of the minimum spanning tree?
Solution
Step 1: Start from vertex 0 and pick smallest edges stepwise
Edges from 0: (0-3)=5, (0-2)=6, (0-1)=10. Pick (0-3)=5 first.Step 2: Add edges connecting new vertices with minimum weight
From visited {0,3}, edges: (3-4)=2, (3-2)=4, (0-2)=6, (0-1)=10. Pick (3-4)=2 next.Step 3: Continue adding minimum edges connecting unvisited vertices
Visited {0,3,4}, edges: (3-2)=4, (0-2)=6, (0-1)=10. Pick (3-2)=4 next.Step 4: Add last vertex 1 with minimum edge
Visited {0,2,3,4}, edges: (0-1)=10, (1-3)=15. Pick (0-1)=10.Step 5: Calculate total weight
Total = 5 + 2 + 4 + 10 = 21.Final Answer:
21 -> Option AQuick Check:
Sum of MST edges = 21 [OK]
- Choosing heavier edges before lighter ones
- Not updating visited set correctly
- Adding edges that create cycles
Ready to prove it?
Pass the test and this pattern moves unknown
