Skip to content
advancedPhase 5 · Graphs

Minimum Spanning Tree

Master Kruskal's and Prim's algorithms for MST problems.

1h 15m
4 problems
Topic Progress0%

MST Concepts and Algorithms

What is a Minimum Spanning Tree?

A Minimum Spanning Tree (MST) of a weighted, connected, undirected graph is a subset of edges that:

  1. Connects all vertices
  2. Has no cycles
  3. Has minimum total edge weight
Original Graph:              MST:
  A —1— B                    A —1— B
  |  X  |                     \\     |
  4   2   3                    4   3
  |     |                      \\   |
  C —5— D                      C —5— D

Total weight: 1+4+2+3+5 = 15
MST weight: 1+3+4 = 8 (edges: A-B, B-D, A-C)

Key Properties

  • Unique MST: If all edge weights are unique, MST is unique
  • |V| - 1 edges: MST always has exactly V-1 edges
  • Cut Property: For any cut, the minimum weight edge crossing the cut is in the MST
  • Cycle Property: For any cycle, the maximum weight edge is not in the MST

Kruskal's Algorithm

Idea: Sort edges by weight, add edges that don't create cycles.

import java.util.*;

public class KruskalMST {
    
    static class Edge {
        int u, v, weight;
        Edge(int u, int v, int weight) {
            this.u = u;
            this.v = v;
            this.weight = weight;
        }
    }
    
    public List<Edge> kruskal(int n, List<Edge> edges) {
        // Sort edges by weight
        edges.sort(Comparator.comparingInt(e -> e.weight));
        
        UnionFind uf = new UnionFind(n);
        List<Edge> mst = new ArrayList<>();
        
        for (Edge edge : edges) {
            // If adding this edge doesn't create a cycle
            if (uf.union(edge.u, edge.v)) {
                mst.add(edge);
                if (mst.size() == n - 1) break;
            }
        }
        
        return mst;
    }
    
    // Union-Find implementation
    static class UnionFind {
        int[] parent, rank;
        
        UnionFind(int n) {
            parent = new int[n];
            rank = new int[n];
            for (int i = 0; i < n; i++) parent[i] = i;
        }
        
        int find(int x) {
            if (parent[x] != x) parent[x] = find(parent[x]);
            return parent[x];
        }
        
        boolean union(int x, int y) {
            int rootX = find(x), rootY = find(y);
            if (rootX == rootY) return false;
            if (rank[rootX] < rank[rootY]) parent[rootX] = rootY;
            else if (rank[rootX] > rank[rootY]) parent[rootY] = rootX;
            else { parent[rootY] = rootX; rank[rootX]++; }
            return true;
        }
    }
}

Time Complexity: O(E log E) or O(E log V)

Prim's Algorithm

Idea: Start from any vertex, always add the minimum weight edge connecting a visited vertex to an unvisited vertex.

import java.util.*;

public class PrimMST {
    
    static class Edge {
        int to, weight;
        Edge(int to, int weight) {
            this.to = to;
            this.weight = weight;
        }
    }
    
    public List<int[]> prim(List<Edge>[] graph, int n) {
        boolean[] inMST = new boolean[n];
        int[] key = new int[n]; // Minimum weight edge to reach this vertex
        int[] parent = new int[n];
        Arrays.fill(key, Integer.MAX_VALUE);
        Arrays.fill(parent, -1);
        key[0] = 0;
        
        // {weight, vertex}
        PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> a[0] - b[0]);
        pq.offer(new int[]{0, 0});
        
        List<int[]> mst = new ArrayList<>();
        
        while (!pq.isEmpty() && mst.size() < n - 1) {
            int[] curr = pq.poll();
            int u = curr[1];
            
            if (inMST[u]) continue;
            inMST[u] = true;
            
            if (parent[u] != -1) {
                mst.add(new int[]{parent[u], u, key[u]});
            }
            
            for (Edge edge : graph[u]) {
                int v = edge.to;
                int weight = edge.weight;
                
                if (!inMST[v] && weight < key[v]) {
                    key[v] = weight;
                    parent[v] = u;
                    pq.offer(new int[]{weight, v});
                }
            }
        }
        
        return mst;
    }
}

Time Complexity: O(E log V) with binary heap

Algorithm Comparison

Aspect Kruskal's Prim's
Approach Edge-centric (sort edges) Vertex-centric (grow tree)
Data Structure Union-Find Priority Queue
Time (binary heap) O(E log E) O(E log V)
Best for Sparse graphs Dense graphs
Parallelization Easier Harder

When to Use Each

Graph Type Better Algorithm
Sparse (E ≈ V) Kruskal's
Dense (E ≈ V²) Prim's
Edge list input Kruskal's
Adjacency list input Prim's
Need to check connectivity first Kruskal's (with Union-Find)

MST Applications and Problems

Common MST Applications

1. Minimum Cost to Connect All Points

public int minCostConnectPoints(int[][] points) {
    int n = points.length;
    List<int[]> edges = new ArrayList<>();
    
    // Create all edges with Manhattan distance
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            int dist = Math.abs(points[i][0] - points[j][0]) 
                     + Math.abs(points[i][1] - points[j][1]);
            edges.add(new int[]{i, j, dist});
        }
    }
    
    // Kruskal's
    edges.sort(Comparator.comparingInt(e -> e[2]));
    UnionFind uf = new UnionFind(n);
    int total = 0;
    int edgesUsed = 0;
    
    for (int[] edge : edges) {
        if (uf.union(edge[0], edge[1])) {
            total += edge[2];
            edgesUsed++;
            if (edgesUsed == n - 1) break;
        }
    }
    
    return total;
}

2. Network Optimization

// Connect cities with minimum cost
public int minimumCost(int n, int[][] connections) {
    List<int[]> edges = new ArrayList<>();
    for (int[] conn : connections) {
        edges.add(new int[]{conn[0] - 1, conn[1] - 1, conn[2]});
    }
    
    edges.sort(Comparator.comparingInt(e -> e[2]));
    UnionFind uf = new UnionFind(n);
    int total = 0;
    int edgesUsed = 0;
    
    for (int[] edge : edges) {
        if (uf.union(edge[0], edge[1])) {
            total += edge[2];
            edgesUsed++;
        }
    }
    
    return edgesUsed == n - 1 ? total : -1;
}

3. Optimize Water Distribution

// kruskal with virtual node for wells
public int minCostToSupplyWater(int n, int[] wells, int[][] pipes) {
    List<int[]> edges = new ArrayList<>();
    
    // Add virtual node 0, edges from wells
    for (int i = 0; i < n; i++) {
        edges.add(new int[]{0, i + 1, wells[i]});
    }
    
    // Add pipe edges
    for (int[] pipe : pipes) {
        edges.add(pipe);
    }
    
    edges.sort(Comparator.comparingInt(e -> e[2]));
    UnionFind uf = new UnionFind(n + 1);
    int total = 0;
    
    for (int[] edge : edges) {
        if (uf.union(edge[0], edge[1])) {
            total += edge[2];
        }
    }
    
    return total;
}

MST Variations

Problem Variation
Minimum Cost Connect Points Standard MST
Optimize Water Distribution Virtual node + MST
Steiner Tree Not exactly MST (NP-hard)
Second Best MST Remove each MST edge, find MST

Problem Pattern Recognition

Problem Key Insight
Connect all points with min cost MST
Wire all houses MST
Network optimization MST
Find redundant connection MST (cycle detection)
Second minimum spanning tree MST + edge replacement

Practice Problems

0/1solved
Min Cost to Connect All Points
Kruskal's Algorithm

Given an array points where points[i] = [xi, yi], return the minimum cost to make all points connected. Cost of connecting points is the Manhattan distance between them.

Example:

Input: points = [[0,0],[2,2],[3,10],[5,2],[7,0]]

Output: 20

Connect: (0,0)→(2,2) cost 4, (2,2)→(3,10) cost 9, (2,2)→(5,2) cost 3, (5,2)→(7,0) cost 4. Total = 20.

Solution
```java
public int minCostConnectPoints(int[][] points) {
    int n = points.length;
    List<int[]> edges = new ArrayList<>();
    
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            int dist = Math.abs(points[i][0] - points[j][0]) 
                     + Math.abs(points[i][1] - points[j][1]);
            edges.add(new int[]{i, j, dist});
        }
    }
    
    edges.sort(Comparator.comparingInt(e -> e[2]));
    
    int[] parent = new int[n];
    int[] rank = new int[n];
    for (int i = 0; i < n; i++) parent[i] = i;
    
    int total = 0;
    int edgesUsed = 0;
    
    for (int[] edge : edges) {
        int root1 = find(parent, edge[0]);
        int root2 = find(parent, edge[1]);
        
        if (root1 != root2) {
            total += edge[2];
            edgesUsed++;
            if (edgesUsed == n - 1) break;
            
            if (rank[root1] < rank[root2]) {
                parent[root1] = root2;
            } else if (rank[root1] > rank[root2]) {
                parent[root2] = root1;
            } else {
                parent[root2] = root1;
                rank[root1]++;
            }
        }
    }
    
    return total;
}

private int find(int[] parent, int x) {
    if (parent[x] != x) parent[x] = find(parent, parent[x]);
    return parent[x];
}
```

Edge Cases:

  • Single point (cost = 0)
  • Two points
  • Points already optimally connected
  • Large coordinate values (overflow potential)

Quiz

1. What is the key difference between Kruskal's and Prim's algorithms?

Question 1 options

2. When is Kruskal's algorithm preferred over Prim's?

Question 2 options

3. What is the primary purpose of Minimum Spanning Tree (MST)?

Question 3 options

4. What is a common mistake when implementing Minimum Spanning Tree (MST)?

Question 4 options

Flashcards

Question

What are the two main algorithms for finding MST?

Answer

1. Kruskal's: Sort edges by weight, add edges that don't create cycles using Union-Find. O(E log E). 2. Prim's: Start from vertex, always add minimum edge to unvisited vertex. O(E log V) with binary heap.

Question

What is the Cut Property in MST?

Answer

For any cut (partition of vertices into two sets), the minimum weight edge crossing the cut must be in the MST. This property is used to prove correctness of both Kruskal's and Prim's algorithms.

Question

What is Minimum Spanning Tree (MST)?

Answer

Minimum Spanning Tree (MST) is a key concept in software engineering.

Question

When to use Minimum Spanning Tree (MST)?

Answer

Use Minimum Spanning Tree (MST) when building production systems that require reliability, scalability, and maintainability.

Question

Minimum Spanning Tree (MST) best practices

Answer

Follow SOLID principles, write clean code, test thoroughly, document decisions, and monitor in production.

Revision Notes

Key Takeaways

  • 1.MST connects all vertices with minimum total edge weight
  • 2.Kruskal's: sort edges, use Union-Find to avoid cycles
  • 3.Prim's: grow tree from vertex, always add minimum edge
  • 4.Kruskal's better for sparse, Prim's better for dense graphs
  • 5.Both algorithms are greedy and produce correct MSTs

Interview Tips

  • Kruskal's is often easier to implement with Union-Find
  • For 'connect all points' problems, think MST
  • Virtual node trick: add well costs as edges from virtual node 0
  • If graph isn't connected, MST doesn't exist (check edge count)
  • Practice: Min Cost Connect Points, Optimize Water Distribution

Cheat Sheet

Minimum Spanning Tree Cheat Sheet

MST Properties

  • Connects all vertices with minimum total weight
  • Has exactly V-1 edges
  • No cycles

Kruskal's Algorithm

edges.sort(Comparator.comparingInt(e -> e.weight));
UnionFind uf = new UnionFind(n);
List<Edge> mst = new ArrayList<>();

for (Edge edge : edges) {
    if (uf.union(edge.u, edge.v)) {
        mst.add(edge);
        if (mst.size() == n - 1) break;
    }
}

Time: O(E log E)

Prim's Algorithm

boolean[] inMST = new boolean[n];
int[] key = new int[n]; // min edge weight to vertex
Arrays.fill(key, Integer.MAX_VALUE);
key[0] = 0;
PriorityQueue<int[]> pq = new PriorityQueue<>((a,b) -> a[0] - b[0]);
pq.offer(new int[]{0, 0});

while (!pq.isEmpty()) {
    int u = pq.poll()[1];
    if (inMST[u]) continue;
    inMST[u] = true;
    for (Edge e : graph[u]) {
        if (!inMST[e.to] && e.weight < key[e.to]) {
            key[e.to] = e.weight;
            pq.offer(new int[]{e.weight, e.to});
        }
    }
}

Time: O(E log V)

Algorithm Selection

Graph Type Algorithm
Sparse (E ≈ V) Kruskal's
Dense (E ≈ V²) Prim's
Edge list Kruskal's
Adjacency list Prim's

Applications

  • Network design (connect cities cheaply)
  • Wire houses with minimum cable
  • Optimize water distribution

Complexity

  • Kruskal's: O(E log E)
  • Prim's: O(E log V) with binary heap