CCCPaste

MST | Kruskals

import java.util.*;

// Kruskal's Algorithm for Minimum Spanning Tree (MST)
class KruskalsAlgorithm {

    // Edge class to represent graph edges
    static class Edge implements Comparable {
        int src, dest, weight;
        Edge(int src, int dest, int weight) {
            this.src = src;
            this.dest = dest;
            this.weight = weight;
        }

        // Sort edges by weight (ascending)
        public int compareTo(Edge other) {
            return this.weight - other.weight;
        }
    }

    // Disjoint Set Union (Union-Find) with path compression + union by rank
    static class DSU {
        int[] parent;
        int[] rank;

        DSU(int n) {
            parent = new int[n];
            rank = new int[n];
            for (int i = 0; i < n; i++) {
                parent[i] = i; // initially, each node is its own parent
                rank[i] = 0;
            }
        }

        // Find the root of a node (with path compression)
        int find(int x) {
            if (parent[x] != x) {
                parent[x] = find(parent[x]); // compress the path
            }
            return parent[x];
        }

        // Union two sets by rank (attach smaller tree under larger one)
        void union(int x, int y) {
            int rootX = find(x);
            int rootY = find(y);

            if (rootX == rootY) return; // already in same set → ignore

            // attach smaller rank tree under the bigger one
            if (rank[rootX] < rank[rootY]) {
                parent[rootX] = rootY;
            } else if (rank[rootX] > rank[rootY]) {
                parent[rootY] = rootX;
            } else {
                parent[rootY] = rootX;
                rank[rootX]++;
            }
        }
    }

    public static int kruskalMST(int V, List edges) {
        // Step 1: Sort all edges by weight
        // ---------------------------------
        // Sorting takes O(E log E)
        Collections.sort(edges);

        DSU dsu = new DSU(V);
        int totalWeight = 0;
        int edgesUsed = 0;

        // Step 2: Iterate over edges in ascending order of weight
        // --------------------------------------------------------
        // Each union/find operation takes ~O(α(V)) ≈ constant time (amortized)
        for (Edge edge : edges) {
            int u = edge.src;
            int v = edge.dest;
            int w = edge.weight;

            // Step 3: Check if adding this edge forms a cycle
            int parentU = dsu.find(u);
            int parentV = dsu.find(v);

            if (parentU != parentV) {
                // Safe to add edge — no cycle
                dsu.union(u, v);
                totalWeight += w;
                edgesUsed++;

                // Optimization: stop once MST has (V - 1) edges
                if (edgesUsed == V - 1) break;
            }
        }

        return totalWeight;
    }

    public static void main(String[] args) {
        // Example Graph (Undirected):
        //     0
        //    / \
        //   1---2
        //   |  /|
        //   | / |
        //   3---4
        //
        // Edges with weights:
        // 0-1:10, 0-2:6, 0-3:5, 1-3:15, 2-3:4, 2-4:2, 3-4:7

        int V = 5;
        List edges = new ArrayList<>();

        edges.add(new Edge(0, 1, 10));
        edges.add(new Edge(0, 2, 6));
        edges.add(new Edge(0, 3, 5));
        edges.add(new Edge(1, 3, 15));
        edges.add(new Edge(2, 3, 4));
        edges.add(new Edge(2, 4, 2));
        edges.add(new Edge(3, 4, 7));

        int mstWeight = kruskalMST(V, edges);
        System.out.println("Total Weight of MST = " + mstWeight);
    }
}