Kruskals MST
#include <bits/stdc++.h> // Includes common standard libraries like iostream, vector, algorithm (for sort), etc.using namespace std; // Use the standard namespace.
// Custom comparison function for sorting edges.// Used by `std::sort` to sort a vector of vectors (representing edges).// Each inner vector `a` or `b` is expected to be `{u, v, weight}`.// We want to sort based on the weight, which is at index 2.bool compare(vector<int> &a, vector<int> &b) { return a[2] < b[2]; // Returns true if weight of 'a' is less than weight of 'b'.}
// ----------------------------------------------------------------------------------// Disjoint Set Union (DSU) / Union-Find Operations// These are fundamental for Kruskal's to detect cycles.// ----------------------------------------------------------------------------------
// findParent: Finds the representative (root) of the set to which 'node' belongs.// Implements Path Compression for optimization.// 'parent': The array where parent[i] stores the parent of node i.// 'node': The current node whose representative needs to be found.int findParent(vector<int> &parent, int node) { // Base Case: If the node is its own parent, it's the root of its set. if(parent[node] == node) { return node; }
// Recursive Step (Going upwards in hierarchy): // Path Compression Logic: // During the recursive call, assign the returned root directly to `parent[node]`. // This flattens the tree by making all nodes in the path point directly to the root, // making future `find` operations for these nodes much faster. return parent[node] = findParent(parent, parent[node]);}
// unionSet: Merges the sets containing 'u' and 'v' using Union by Rank optimization.// 'u', 'v': The two nodes whose sets are to be merged.// 'parent': The parent array.// 'rank': The rank array (stores approximate height of trees).void unionSet(int u, int v, vector<int> &parent, vector<int> &rank) { // Find the representatives (roots) of the sets containing 'u' and 'v'. // These will already be 'compressed' if findParent uses path compression. u = findParent(parent, u); v = findParent(parent, v);
// If 'u' and 'v' are already in the same set (have the same root), do nothing. // This check is typically done *before* calling unionSet in Kruskal's. if(u == v) { return; // Already in the same component. }
// Union by Rank: Attach the root of the smaller rank tree under the root of the larger rank tree. // This helps in keeping the overall tree height minimal, improving findParent performance. if(rank[u] < rank[v]) { parent[u] = v; // Make 'v' the parent of 'u'. } else if(rank[v] < rank[u]) { parent[v] = u; // Make 'u' the parent of 'v'. } else { // If ranks are equal, either can be parent. Choose 'u' to be parent of 'v'. parent[v] = u; rank[u]++; // Increment the rank of the new root 'u' because its height effectively increased. }}
// ----------------------------------------------------------------------------------// Kruskal's Algorithm Implementation// ----------------------------------------------------------------------------------
// calculateKruskalsMST: Calculates the total weight of the Minimum Spanning Tree using Kruskal's algorithm.// 'edges': A vector of vectors, where each inner vector is {u, v, w} representing an edge.// 'n': Total number of nodes in the graph (0 to n-1).// Returns the total minimum weight of the MST.int calculateKruskalsMST(vector<vector<int>> &edges, int n) { // 1. Initialize Disjoint Set Union (DSU) structure. // 'parent' array: Each node is initially its own parent. // 'rank' array: Initial rank of each set is 0. vector<int> parent(n); vector<int> rank(n); for(int i = 0; i < n; i++) { parent[i] = i; rank[i] = 0; }
// 2. Sort all edges by their weights in non-decreasing order. // This is the crucial greedy step of Kruskal's. sort(edges.begin(), edges.end(), compare);
// 'minWeight' will store the sum of weights of edges included in the MST. int minWeight = 0;
// 3. Iterate through the sorted edges. for(int i = 0; i < edges.size(); i++) { int u_node = edges[i][0]; // Source node of the current edge. int v_node = edges[i][1]; // Destination node of the current edge. int weight = edges[i][2]; // Weight of the current edge.
// Find the representatives (roots) of the sets containing u_node and v_node. int rootU = findParent(parent, u_node); int rootV = findParent(parent, v_node);
// Check for cycle: If the roots are different, adding this edge will NOT form a cycle. if(rootU != rootV) { // Merge the sets of u_node and v_node. unionSet(rootU, rootV, parent, rank); // Add the weight of this edge to the total MST weight. minWeight += weight;
// If you needed to return the MST edges themselves, you would add {u_node, v_node, weight} // to a separate result vector here. } // If rootU == rootV, adding this edge would form a cycle, so we skip it. }
return minWeight; // Return the total weight of the Minimum Spanning Tree.}
// ----------------------------------------------------------------------------------// Main Function for input/output.// ----------------------------------------------------------------------------------
int main() { vector<vector<int>> edges; // Stores input edges as {u, v, w}. int n, m; // 'n' for number of nodes, 'm' for number of edges.
cout << "Enter the number of nodes : "; cin >> n;
cout << "Enter the number of edges : "; cin >> m;
cout << "Enter the edges (u v w): " << endl; for(int i = 0; i < m; i++) { int u, v, w; cin >> u >> v >> w; // Read source, destination, and weight. edges.push_back({u, v, w}); // Add edge to vector. }
// Calculate the total weight of the Kruskal's MST. int minWeight = calculateKruskalsMST(edges, n);
cout << "Weight of Kruskal's MST : " << minWeight << endl;
return 0; // Indicate successful execution.}
1. Problem Statement
- Goal: Find a Minimum Spanning Tree (MST) of a connected, undirected, weighted graph.
- MST Definition: A spanning tree that connects all vertices using
V-1
edges, without cycles, and with the minimum possible total edge weight. - Input: A list of weighted
edges (u, v, w)
, and the total number ofn
nodes. The number of edgesm
is implicitly handled by theedges.size()
. - Output: The total minimum weight of the MST. (The code currently returns only the total weight, not the edges themselves).
2. Core Idea (Kruskal’s Algorithm - Greedy Approach)
Kruskal’s algorithm is a greedy algorithm that builds the MST by considering edges in increasing order of their weights. It uses the Disjoint Set Union (DSU) data structure to efficiently detect and prevent cycles.
- Sort Edges: All edges are sorted in non-decreasing order of their weights.
- Iterate and Add: Iterate through the sorted edges. For each edge
(u, v, w)
:- Cycle Check: Use DSU’s
findParent
operation to check ifu
andv
are already in the same connected component (i.e., if adding this edge would form a cycle). - Add to MST: If
u
andv
are in different components, add this edge to the MST. Update the total MST weight. Then, use DSU’sunionSet
operation to merge the components ofu
andv
. - Skip: If
u
andv
are already in the same component, skip this edge as it would form a cycle.
- Cycle Check: Use DSU’s
- Termination: The algorithm stops when
N-1
edges have been added to the MST (for a connected graph withN
nodes), or when all edges have been processed.
3. Key Components and Algorithm Steps
A. Disjoint Set Union (DSU) Functions (Reused from previous notes)
findParent(vector<int> &parent, int node)
:- Finds the representative (root) of the set containing
node
. - Path Compression Optimization: Flattens the tree by making all nodes in the path point directly to the root, optimizing future
find
calls.
- Finds the representative (root) of the set containing
unionSet(int u, int v, vector<int> &parent, vector<int> &rank)
:- Merges the sets containing
u
andv
. - Union by Rank Optimization: Attaches the root of the shorter tree to the root of the taller tree to keep the overall tree height small.
- Merges the sets containing
B. Edge Comparison Function (compare
)
bool compare(vector<int> &a, vector<int> &b)
:- A custom comparison function used with
std::sort
. - It takes two edge representations (e.g.,
vector<int>
wherea[2]
is weight) and returnstrue
ifa
should come beforeb
in sorted order based on their weights. (a[2] < b[2]
).
- A custom comparison function used with
C. calculateKruskalsMST(vector<vector<int>> &edges, int n)
Function
-
Initialize DSU:
- Create
vector<int> parent(n)
andvector<int> rank(n)
. - For each node
i
from0
ton-1
:parent[i] = i
(each node starts in its own set),rank[i] = 0
.
- Create
-
Sort Edges:
sort(edges.begin(), edges.end(), compare);
Sorts all input edges by their weights in non-decreasing order.
-
Initialize MST Weight:
int minWeight = 0;
(This variable will accumulate the total weight of edges added to the MST).
-
Iterate Through Sorted Edges:
- Loop through each edge
edges[i]
in the sortededges
vector:- Extract
u = edges[i][0]
,v = edges[i][1]
,w = edges[i][2]
. - Cycle Check: Find the representatives of
u
andv
:rootU = findParent(parent, u)
androotV = findParent(parent, v)
. - If no cycle (different roots):
unionSet(rootU, rootV, parent, rank);
(Merge the sets ofu
andv
).minWeight += w;
(Add the edge’s weight to the total MST weight).
- If cycle (same roots):
- Do nothing, as adding this edge would create a cycle.
- Extract
- Loop through each edge
-
Return:
minWeight
(the total weight of the MST).
4. Time and Space Complexity
- Time Complexity:
O(E log E + E α(V))
- Sorting edges:
O(E log E)
(whereE
is the number of edges). - DSU operations:
E
timesfindParent
andunionSet
operations. With path compression and union by rank, this isO(E α(V))
(whereα
is the inverse Ackermann function, practically constant). - Total: Dominated by sorting, so
O(E log E)
orO(E log V)
(sinceE <= V^2
,log E
is at most2 log V
).
- Sorting edges:
- Space Complexity:
O(V + E)
parent
andrank
arrays:O(V)
.- Storing
edges
:O(E)
.
5. Important Notes
- Connectivity: Kruskal’s algorithm assumes the graph is connected. If the graph is not connected, it will find a Minimum Spanning Forest (a set of MSTs for each connected component). The returned
minWeight
would be the sum of weights of all such MSTs. - Edge List Input: Kruskal’s algorithm is naturally suited for graphs represented by an edge list, as it requires sorting all edges.
- Outputting MST Edges: The provided code only sums the total weight. To get the actual edges of the MST, you would store the
(u, v, w)
of the edges that satisfyu != v
in a separatevector
before returning.