🧠
Brute Force (Try All Subsets of Edges)
💡 This approach exists to understand the problem's combinatorial nature and why naive attempts are infeasible. It helps grasp the connectivity requirements before optimizing.
Intuition
Try every subset of edges to check if both Alice and Bob can traverse the entire graph. Count how many edges can be removed while maintaining full connectivity for both.
Algorithm
- Generate all subsets of edges.
- For each subset, build two graphs: one for Alice (type 1 and 3 edges) and one for Bob (type 2 and 3 edges).
- Check if both graphs are fully connected.
- Track the maximum number of edges removed among valid subsets.
💡 This algorithm is hard to see because it involves exponential subsets and separate connectivity checks for two users.
from itertools import combinations
def max_num_edges_to_remove_bruteforce(n, edges):
max_remove = -1
m = len(edges)
# Check connectivity using DFS
def is_connected(graph):
visited = set()
def dfs(u):
visited.add(u)
for v in graph[u]:
if v not in visited:
dfs(v)
dfs(1)
return len(visited) == n
for r in range(m + 1):
for subset in combinations(edges, m - r):
alice_graph = {i: [] for i in range(1, n + 1)}
bob_graph = {i: [] for i in range(1, n + 1)}
for t, u, v in subset:
if t == 1 or t == 3:
alice_graph[u].append(v)
alice_graph[v].append(u)
if t == 2 or t == 3:
bob_graph[u].append(v)
bob_graph[v].append(u)
if is_connected(alice_graph) and is_connected(bob_graph):
max_remove = max(max_remove, r)
return max_remove
# Example usage
if __name__ == '__main__':
n = 4
edges = [[3,1,2],[3,2,3],[1,1,3],[1,2,4],[1,1,2],[2,3,4]]
print(max_num_edges_to_remove_bruteforce(n, edges)) # Output: 2
Line Notes
from itertools import combinationsImport combinations to generate all subsets of edges
def is_connected(graph):Helper function to check if a graph is fully connected
for r in range(m + 1):Try removing r edges from the graph
for subset in combinations(edges, m - r):Generate all subsets with m-r edges to keep
if is_connected(alice_graph) and is_connected(bob_graph):Check if both Alice and Bob can traverse the graph
return max_removeReturn the maximum number of edges that can be removed
import java.util.*;
public class Solution {
// Helper class to represent graph and check connectivity
static class Graph {
Map<Integer, List<Integer>> adj;
int n;
Graph(int n) {
this.n = n;
adj = new HashMap<>();
for (int i = 1; i <= n; i++) adj.put(i, new ArrayList<>());
}
void addEdge(int u, int v) {
adj.get(u).add(v);
adj.get(v).add(u);
}
boolean isConnected() {
Set<Integer> visited = new HashSet<>();
dfs(1, visited);
return visited.size() == n;
}
void dfs(int u, Set<Integer> visited) {
visited.add(u);
for (int v : adj.get(u)) {
if (!visited.contains(v)) dfs(v, visited);
}
}
}
// Generate all combinations of edges of size k
static void combinations(int[][] edges, int start, int k, List<int[]> current, List<List<int[]>> result) {
if (current.size() == k) {
result.add(new ArrayList<>(current));
return;
}
for (int i = start; i < edges.length; i++) {
current.add(edges[i]);
combinations(edges, i + 1, k, current, result);
current.remove(current.size() - 1);
}
}
public static int maxNumEdgesToRemoveBruteForce(int n, int[][] edges) {
int maxRemove = -1;
int m = edges.length;
for (int r = 0; r <= m; r++) {
List<List<int[]>> subsets = new ArrayList<>();
combinations(edges, 0, m - r, new ArrayList<>(), subsets);
for (List<int[]> subset : subsets) {
Graph aliceGraph = new Graph(n);
Graph bobGraph = new Graph(n);
for (int[] edge : subset) {
int t = edge[0], u = edge[1], v = edge[2];
if (t == 1 || t == 3) {
aliceGraph.addEdge(u, v);
}
if (t == 2 || t == 3) {
bobGraph.addEdge(u, v);
}
}
if (aliceGraph.isConnected() && bobGraph.isConnected()) {
maxRemove = Math.max(maxRemove, r);
}
}
}
return maxRemove;
}
public static void main(String[] args) {
int n = 4;
int[][] edges = {{3,1,2},{3,2,3},{1,1,3},{1,2,4},{1,1,2},{2,3,4}};
System.out.println(maxNumEdgesToRemoveBruteForce(n, edges)); // Output: 2
}
Line Notes
static class Graph {Helper class to represent graph and check connectivity
void dfs(int u, Set<Integer> visited) {DFS to traverse graph nodes
for (int r = 0; r <= m; r++) {Try removing r edges from the graph
combinations(edges, 0, m - r, new ArrayList<>(), subsets);Generate all subsets with m-r edges to keep
if (aliceGraph.isConnected() && bobGraph.isConnected()) {Check connectivity for both Alice and Bob
return maxRemove;Return maximum removable edges
#include <bits/stdc++.h>
using namespace std;
class Graph {
public:
unordered_map<int, vector<int>> adj;
int n;
Graph(int n) : n(n) {
for (int i = 1; i <= n; i++) adj[i] = {};
}
void addEdge(int u, int v) {
adj[u].push_back(v);
adj[v].push_back(u);
}
void dfs(int u, unordered_set<int>& visited) {
visited.insert(u);
for (int v : adj[u]) {
if (!visited.count(v)) dfs(v, visited);
}
}
bool isConnected() {
unordered_set<int> visited;
dfs(1, visited);
return visited.size() == n;
}
};
void combinations(const vector<vector<int>>& edges, int start, int k, vector<vector<int>>& current, vector<vector<vector<int>>>& result) {
if ((int)current.size() == k) {
result.push_back(current);
return;
}
for (int i = start; i < (int)edges.size(); i++) {
current.push_back(edges[i]);
combinations(edges, i + 1, k, current, result);
current.pop_back();
}
}
int maxNumEdgesToRemoveBruteForce(int n, vector<vector<int>>& edges) {
int maxRemove = -1;
int m = (int)edges.size();
for (int r = 0; r <= m; r++) {
vector<vector<vector<int>>> subsets;
vector<vector<int>> current;
combinations(edges, 0, m - r, current, subsets);
for (auto& subset : subsets) {
Graph aliceGraph(n), bobGraph(n);
for (auto& e : subset) {
int t = e[0], u = e[1], v = e[2];
if (t == 1 || t == 3) aliceGraph.addEdge(u, v);
if (t == 2 || t == 3) bobGraph.addEdge(u, v);
}
if (aliceGraph.isConnected() && bobGraph.isConnected()) {
maxRemove = max(maxRemove, r);
}
}
}
return maxRemove;
}
int main() {
int n = 4;
vector<vector<int>> edges = {{3,1,2},{3,2,3},{1,1,3},{1,2,4},{1,1,2},{2,3,4}};
cout << maxNumEdgesToRemoveBruteForce(n, edges) << "\n"; // Output: 2
return 0;
}
Line Notes
class Graph {Graph class to store adjacency and check connectivity
void dfs(int u, unordered_set<int>& visited) {DFS traversal to mark visited nodes
for (int r = 0; r <= m; r++) {Try removing r edges from the graph
combinations(edges, 0, m - r, current, subsets);Generate all subsets with m-r edges to keep
if (aliceGraph.isConnected() && bobGraph.isConnected()) {Check if both graphs are connected
return maxRemove;Return maximum number of removable edges
function maxNumEdgesToRemoveBruteforce(n, edges) {
const m = edges.length;
let maxRemove = -1;
function isConnected(graph) {
const visited = new Set();
function dfs(u) {
visited.add(u);
for (const v of graph.get(u) || []) {
if (!visited.has(v)) dfs(v);
}
}
dfs(1);
return visited.size === n;
}
function* combinations(arr, k, start = 0, path = []) {
if (path.length === k) {
yield path;
return;
}
for (let i = start; i < arr.length; i++) {
yield* combinations(arr, k, i + 1, path.concat(arr[i]));
}
}
for (let r = 0; r <= m; r++) {
for (const subset of combinations(edges, m - r)) {
const aliceGraph = new Map();
const bobGraph = new Map();
for (const [t, u, v] of subset) {
if (t === 1 || t === 3) {
if (!aliceGraph.has(u)) aliceGraph.set(u, []);
if (!aliceGraph.has(v)) aliceGraph.set(v, []);
aliceGraph.get(u).push(v);
aliceGraph.get(v).push(u);
}
if (t === 2 || t === 3) {
if (!bobGraph.has(u)) bobGraph.set(u, []);
if (!bobGraph.has(v)) bobGraph.set(v, []);
bobGraph.get(u).push(v);
bobGraph.get(v).push(u);
}
}
if (isConnected(aliceGraph) && isConnected(bobGraph)) {
maxRemove = Math.max(maxRemove, r);
}
}
}
return maxRemove;
}
// Example usage
const n = 4;
const edges = [[3,1,2],[3,2,3],[1,1,3],[1,2,4],[1,1,2],[2,3,4]];
console.log(maxNumEdgesToRemoveBruteforce(n, edges)); // Output: 2
Line Notes
function isConnected(graph) {Helper to check if graph is fully connected
function* combinations(arr, k, start = 0, path = []) {Generator to produce all subsets of edges
for (let r = 0; r <= m; r++) {Try removing r edges from the graph
if (isConnected(aliceGraph) && isConnected(bobGraph)) {Check connectivity for both Alice and Bob
return maxRemove;Return maximum removable edges found
TimeO(2^m * (n + m))
SpaceO(n + m)
We try all subsets of edges (2^m), and for each subset, we check connectivity for Alice and Bob using DFS (O(n + m)).
💡 For n=4 and m=6, this means 64 subsets and connectivity checks, which is already slow. For large n, this is impossible.
Interview Verdict: TLE
This approach is too slow for large inputs but helps understand the problem and why optimization is needed.