🧠
Brute Force (Check All Edge Subsets)
💡 This approach exists to understand the problem from first principles by trying all possible subsets of edges to find the MST. It is impractical for large inputs but helps grasp the MST definition and why optimization is needed.
Intuition
Try every combination of edges that connects all nodes without cycles and pick the one with the minimum total weight.
Algorithm
- Generate all subsets of edges with size n-1 (since MST has n-1 edges).
- For each subset, check if it connects all nodes and contains no cycles.
- Calculate the total weight of the subset if valid.
- Return the minimum total weight among all valid subsets.
💡 The challenge is enumerating subsets and checking connectivity and cycles, which is computationally expensive and hard to implement efficiently.
from itertools import combinations
def find(parent, x):
while parent[x] != x:
x = parent[x]
return x
def union(parent, rank, x, y):
rx, ry = find(parent, x), find(parent, y)
if rx == ry:
return False
if rank[rx] < rank[ry]:
parent[rx] = ry
elif rank[ry] < rank[rx]:
parent[ry] = rx
else:
parent[ry] = rx
rank[rx] += 1
return True
def brute_force_mst(n, edges):
if n == 1:
return 0 # MST weight is 0 for single node
min_weight = float('inf')
for subset in combinations(edges, n - 1):
parent = list(range(n))
rank = [0] * n
total = 0
valid = True
for u, v, w in subset:
if not union(parent, rank, u, v):
valid = False
break
total += w
if valid:
# Check if all nodes connected
root = find(parent, 0)
if all(find(parent, i) == root for i in range(n)):
min_weight = min(min_weight, total)
return min_weight if min_weight != float('inf') else -1
# Example usage
if __name__ == '__main__':
n = 4
edges = [(0,1,1),(1,2,2),(0,2,3),(2,3,4)]
print(brute_force_mst(n, edges))
Line Notes
from itertools import combinationsImport combinations to generate all edge subsets
def find(parent, x):Define find to locate root of a node for cycle detection
def union(parent, rank, x, y):Define union to merge sets and detect cycles
if n == 1:Handle single node graph where MST weight is 0
for subset in combinations(edges, n - 1):Try every subset of edges of size n-1
if not union(parent, rank, u, v):If union fails, a cycle is detected, discard subset
if all(find(parent, i) == root for i in range(n))Check if all nodes are connected
return min_weight if min_weight != float('inf') else -1Return MST weight or -1 if none found
import java.util.*;
public class BruteForceMST {
static int find(int[] parent, int x) {
while (parent[x] != x) {
x = parent[x];
}
return x;
}
static boolean union(int[] parent, int[] rank, int x, int y) {
int rx = find(parent, x);
int ry = find(parent, y);
if (rx == ry) return false;
if (rank[rx] < rank[ry]) parent[rx] = ry;
else if (rank[ry] < rank[rx]) parent[ry] = rx;
else {
parent[ry] = rx;
rank[rx]++;
}
return true;
}
static boolean nextCombination(int[] comb, int n, int k) {
int i = k - 1;
while (i >= 0 && comb[i] == n - k + i) i--;
if (i < 0) return false;
comb[i]++;
for (int j = i + 1; j < k; j++) comb[j] = comb[j - 1] + 1;
return true;
}
static int bruteForceMST(int n, List<int[]> edges) {
if (n == 1) return 0; // MST weight is 0 for single node
int minWeight = Integer.MAX_VALUE;
int m = edges.size();
int[] indices = new int[n - 1];
for (int i = 0; i < n - 1; i++) indices[i] = i;
while (true) {
int[] parent = new int[n];
int[] rank = new int[n];
for (int i = 0; i < n; i++) parent[i] = i;
int total = 0;
boolean valid = true;
for (int idx : indices) {
int[] e = edges.get(idx);
if (!union(parent, rank, e[0], e[1])) {
valid = false;
break;
}
total += e[2];
}
if (valid) {
int root = find(parent, 0);
boolean connected = true;
for (int i = 0; i < n; i++) {
if (find(parent, i) != root) {
connected = false;
break;
}
}
if (connected) minWeight = Math.min(minWeight, total);
}
if (!nextCombination(indices, m, n - 1)) break;
}
return minWeight == Integer.MAX_VALUE ? -1 : minWeight;
}
public static void main(String[] args) {
int n = 4;
List<int[]> edges = Arrays.asList(
new int[]{0,1,1},
new int[]{1,2,2},
new int[]{0,2,3},
new int[]{2,3,4}
);
System.out.println(bruteForceMST(n, edges));
}
}
Line Notes
static int find(int[] parent, int x)Find root of x for cycle detection
static boolean union(int[] parent, int[] rank, int x, int y)Union sets and detect cycles
if (n == 1) return 0;Handle single node graph where MST weight is 0
for (int idx : indices)Iterate over current combination of edges
if (!union(parent, rank, e[0], e[1]))Cycle detected, discard this subset
if (!nextCombination(indices, m, n - 1)) break;Generate next combination of edges
int root = find(parent, 0);Check connectivity by verifying all nodes share root
return minWeight == Integer.MAX_VALUE ? -1 : minWeight;Return MST weight or -1 if none found
#include <bits/stdc++.h>
using namespace std;
int find_set(vector<int>& parent, int v) {
while (parent[v] != v) v = parent[v];
return v;
}
bool union_set(vector<int>& parent, vector<int>& rank, int a, int b) {
a = find_set(parent, a);
b = find_set(parent, b);
if (a == b) return false;
if (rank[a] < rank[b]) parent[a] = b;
else if (rank[b] < rank[a]) parent[b] = a;
else {
parent[b] = a;
rank[a]++;
}
return true;
}
bool next_combination(vector<int>& comb, int n, int k) {
int i = k - 1;
while (i >= 0 && comb[i] == n - k + i) i--;
if (i < 0) return false;
comb[i]++;
for (int j = i + 1; j < k; j++) comb[j] = comb[j - 1] + 1;
return true;
}
int brute_force_mst(int n, vector<array<int,3>>& edges) {
if (n == 1) return 0; // MST weight is 0 for single node
int m = (int)edges.size();
vector<int> comb(n - 1);
iota(comb.begin(), comb.end(), 0);
int min_weight = INT_MAX;
do {
vector<int> parent(n), rank(n, 0);
iota(parent.begin(), parent.end(), 0);
int total = 0;
bool valid = true;
for (int idx : comb) {
auto& e = edges[idx];
if (!union_set(parent, rank, e[0], e[1])) {
valid = false;
break;
}
total += e[2];
}
if (valid) {
int root = find_set(parent, 0);
bool connected = true;
for (int i = 0; i < n; i++) {
if (find_set(parent, i) != root) {
connected = false;
break;
}
}
if (connected) min_weight = min(min_weight, total);
}
} while (next_combination(comb, m, n - 1));
return min_weight == INT_MAX ? -1 : min_weight;
}
int main() {
int n = 4;
vector<array<int,3>> edges = {{0,1,1},{1,2,2},{0,2,3},{2,3,4}};
cout << brute_force_mst(n, edges) << "\n";
return 0;
}
Line Notes
int find_set(vector<int>& parent, int v)Find root of node v for cycle detection
bool union_set(vector<int>& parent, vector<int>& rank, int a, int b)Union two sets and detect cycles
if (n == 1) return 0;Handle single node graph where MST weight is 0
do { ... } while (next_combination(comb, m, n - 1));Generate all combinations of edges
if (!union_set(parent, rank, e[0], e[1]))Cycle detected, discard this subset
int root = find_set(parent, 0);Check if all nodes connected by comparing roots
return min_weight == INT_MAX ? -1 : min_weight;Return MST weight or -1 if none found
function find(parent, x) {
while (parent[x] !== x) {
x = parent[x];
}
return x;
}
function union(parent, rank, x, y) {
let rx = find(parent, x);
let ry = find(parent, y);
if (rx === ry) return false;
if (rank[rx] < rank[ry]) parent[rx] = ry;
else if (rank[ry] < rank[rx]) parent[ry] = rx;
else {
parent[ry] = rx;
rank[rx]++;
}
return true;
}
function nextCombination(comb, n, k) {
let i = k - 1;
while (i >= 0 && comb[i] === n - k + i) i--;
if (i < 0) return false;
comb[i]++;
for (let j = i + 1; j < k; j++) {
comb[j] = comb[j - 1] + 1;
}
return true;
}
function bruteForceMST(n, edges) {
if (n === 1) return 0; // MST weight is 0 for single node
let m = edges.length;
let comb = Array.from({length: n - 1}, (_, i) => i);
let minWeight = Infinity;
do {
let parent = Array.from({length: n}, (_, i) => i);
let rank = Array(n).fill(0);
let total = 0;
let valid = true;
for (let idx of comb) {
let [u, v, w] = edges[idx];
if (!union(parent, rank, u, v)) {
valid = false;
break;
}
total += w;
}
if (valid) {
let root = find(parent, 0);
let connected = true;
for (let i = 0; i < n; i++) {
if (find(parent, i) !== root) {
connected = false;
break;
}
}
if (connected) minWeight = Math.min(minWeight, total);
}
} while (nextCombination(comb, m, n - 1));
return minWeight === Infinity ? -1 : minWeight;
}
// Example usage
const n = 4;
const edges = [[0,1,1],[1,2,2],[0,2,3],[2,3,4]];
console.log(bruteForceMST(n, edges));
Line Notes
function find(parent, x)Find root of x for cycle detection
function union(parent, rank, x, y)Union sets and detect cycles
if (n === 1) return 0;Handle single node graph where MST weight is 0
do { ... } while (nextCombination(comb, m, n - 1));Generate all edge subsets of size n-1
if (!union(parent, rank, u, v))Cycle detected, discard this subset
let root = find(parent, 0);Check connectivity by verifying all nodes share root
return minWeight === Infinity ? -1 : minWeight;Return MST weight or -1 if none found
TimeO(C(m, n-1) * n * α(n)) where C(m, n-1) is combinations of edges, α is inverse Ackermann
SpaceO(n) for Union-Find arrays
We try all subsets of edges of size n-1, which is combinatorial and grows exponentially. Each subset requires union-find operations to check cycles and connectivity.
💡 For n=4 and m=4 edges, this means checking 4 choose 3 = 4 subsets, which is manageable. For n=20, this explodes to billions of subsets, making it impractical.
Interview Verdict: TLE
This approach is too slow for large inputs but is useful to understand the problem and why efficient algorithms like Kruskal's exist.