1. Generate All Spanning Trees (Combinatorial / DFS Cycle Check)
Intuition
A spanning tree is any subset of V - 1 edges from the E available edges that forms a connected tree without cycles. We could generate all \binom{E}{V-1} subsets of edges, test each subset for connectivity and acyclicity using DFS, and find the subset with minimum total weight. This demonstrates the combinatorial explosion that greedy algorithms avoid.
Algorithm
- Generate all combinations of V - 1 edges from the total E edges.
- For each combination of V - 1 edges:
- Construct an adjacency graph using only those edges.
- Run DFS/BFS from node 0 to verify all V vertices are reachable (connected and therefore acyclic since edge count is V - 1).
- If valid, calculate sum of edge weights and update global minimum MST weight.
- Return the minimum sum found.
#include <iostream>#include <vector>#include <numeric>#include <climits> struct Edge { int u, v, w;}; void checkSubsets(int idx, int picked, int V, const std::vector<Edge>& edges, std::vector<Edge>& current, int& minSum) { if (picked == V - 1) { // Check connectivity std::vector<std::vector<int>> adj(V); int sum = 0; for (const auto& e : current) { adj[e.u].push_back(e.v); adj[e.v].push_back(e.u); sum += e.w; } std::vector<bool> visited(V, false); auto dfs = [&](auto& self, int u) -> void { visited[u] = true; for (int v : adj[u]) { if (!visited[v]) self(self, v); } }; dfs(dfs, 0); bool connected = true; for (int i = 0; i < V; ++i) if (!visited[i]) connected = false; if (connected) minSum = std::min(minSum, sum); return; } if (idx >= edges.size()) return; // Pick edge current.push_back(edges[idx]); checkSubsets(idx + 1, picked + 1, V, edges, current, minSum); current.pop_back(); // Skip edge checkSubsets(idx + 1, picked, V, edges, current, minSum);} int spanningTreeBrute(int V, const std::vector<Edge>& edges) { int minSum = INT_MAX; std::vector<Edge> current; checkSubsets(0, 0, V, edges, current, minSum); return minSum;} int main() { int V = 3; std::vector<Edge> edges = {{0, 1, 5}, {1, 2, 3}, {0, 2, 1}}; std::cout << "Brute Force MST: " << spanningTreeBrute(V, edges) << std::endl; return 0;}Time & Space Complexity
- Time complexity:
O(C(E, V-1) * (V + E)) which is exponential and completely impractical for E, V > 20. - Space complexity:
O(V + E) to store edge subsets and adjacency representation for validation.