🧠
Brute Force (Check Reachability from Every Node)
💡 This approach exists to build intuition by trying all possible starting nodes and checking if they can reach all nodes. It is inefficient but helps understand the problem deeply.
Intuition
Try starting a DFS or BFS from each node and see if all nodes are reachable. Collect nodes that can reach all others.
Algorithm
- For each node from 0 to n-1:
- Perform DFS/BFS to find all reachable nodes.
- If the reachable set includes all nodes, add this node to the candidate set.
- Return the minimal candidate set found (or all such nodes).
💡 This algorithm is straightforward but inefficient because it repeats expensive traversals for every node.
from collections import deque
def findSmallestSetOfVertices(n, edges):
graph = [[] for _ in range(n)]
for u, v in edges:
graph[u].append(v)
def bfs(start):
visited = set()
queue = deque([start])
while queue:
node = queue.popleft()
if node not in visited:
visited.add(node)
for nei in graph[node]:
if nei not in visited:
queue.append(nei)
return visited
result = []
for i in range(n):
reachable = bfs(i)
if len(reachable) == n:
result.append(i)
return result
# Example usage:
if __name__ == '__main__':
n = 6
edges = [[0,1],[0,2],[2,5],[3,4],[4,2]]
print(findSmallestSetOfVertices(n, edges))
Line Notes
graph = [[] for _ in range(n)]Initialize adjacency list for graph representation
for u, v in edges:Build graph edges for traversal
def bfs(start):Define BFS to find reachable nodes from start
visited = set()Track visited nodes to avoid cycles and repeated visits
queue = deque([start])Initialize queue with start node for BFS
while queue:Process nodes in BFS order
node = queue.popleft()Get current node to explore neighbors
if node not in visited:Process node only if not visited
for nei in graph[node]:Explore all neighbors of current node
if nei not in visited:Add unvisited neighbors to queue
result = []Store nodes that can reach all others
for i in range(n):Check reachability from every node
reachable = bfs(i)Get reachable nodes from node i
if len(reachable) == n:If all nodes reachable, add to result
return resultReturn all nodes that can reach entire graph
import java.util.*;
public class Solution {
public static List<Integer> findSmallestSetOfVertices(int n, int[][] edges) {
List<List<Integer>> graph = new ArrayList<>();
for (int i = 0; i < n; i++) graph.add(new ArrayList<>());
for (int[] edge : edges) graph.get(edge[0]).add(edge[1]);
List<Integer> result = new ArrayList<>();
for (int i = 0; i < n; i++) {
if (bfs(i, graph, n)) result.add(i);
}
return result;
}
private static boolean bfs(int start, List<List<Integer>> graph, int n) {
boolean[] visited = new boolean[n];
Queue<Integer> queue = new LinkedList<>();
queue.offer(start);
int count = 0;
while (!queue.isEmpty()) {
int node = queue.poll();
if (!visited[node]) {
visited[node] = true;
count++;
for (int nei : graph.get(node)) {
if (!visited[nei]) queue.offer(nei);
}
}
}
return count == n;
}
public static void main(String[] args) {
int n = 6;
int[][] edges = {{0,1},{0,2},{2,5},{3,4},{4,2}};
System.out.println(findSmallestSetOfVertices(n, edges));
}
Line Notes
List<List<Integer>> graph = new ArrayList<>();Initialize adjacency list for graph
for (int[] edge : edges)Build graph edges
List<Integer> result = new ArrayList<>();Store nodes that reach all others
for (int i = 0; i < n; i++)Check reachability from each node
if (bfs(i, graph, n))If BFS from i reaches all nodes, add i
boolean[] visited = new boolean[n];Track visited nodes in BFS
Queue<Integer> queue = new LinkedList<>();Initialize BFS queue
queue.offer(start);Start BFS from node
while (!queue.isEmpty())Process BFS queue
if (!visited[node])Process unvisited nodes
count++Count how many nodes visited
return count == n;Check if all nodes reached
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
vector<int> findSmallestSetOfVertices(int n, vector<vector<int>>& edges) {
vector<vector<int>> graph(n);
for (auto& e : edges) {
graph[e[0]].push_back(e[1]);
}
vector<int> result;
for (int i = 0; i < n; i++) {
vector<bool> visited(n, false);
queue<int> q;
q.push(i);
int count = 0;
while (!q.empty()) {
int node = q.front(); q.pop();
if (!visited[node]) {
visited[node] = true;
count++;
for (int nei : graph[node]) {
if (!visited[nei]) q.push(nei);
}
}
}
if (count == n) result.push_back(i);
}
return result;
}
int main() {
int n = 6;
vector<vector<int>> edges = {{0,1},{0,2},{2,5},{3,4},{4,2}};
vector<int> res = findSmallestSetOfVertices(n, edges);
for (int v : res) cout << v << ' ';
cout << endl;
return 0;
}
Line Notes
vector<vector<int>> graph(n);Initialize adjacency list
for (auto& e : edges)Build graph edges
vector<int> result;Store nodes that reach all others
for (int i = 0; i < n; i++)Check reachability from each node
vector<bool> visited(n, false);Track visited nodes for BFS
queue<int> q;Initialize BFS queue
q.push(i);Start BFS from node i
while (!q.empty())Process BFS queue
if (!visited[node])Process unvisited nodes
count++Count visited nodes
if (count == n) result.push_back(i);If all nodes reached, add i
function findSmallestSetOfVertices(n, edges) {
const graph = Array.from({length: n}, () => []);
for (const [u, v] of edges) {
graph[u].push(v);
}
function bfs(start) {
const visited = new Set();
const queue = [start];
while (queue.length > 0) {
const node = queue.shift();
if (!visited.has(node)) {
visited.add(node);
for (const nei of graph[node]) {
if (!visited.has(nei)) queue.push(nei);
}
}
}
return visited;
}
const result = [];
for (let i = 0; i < n; i++) {
const reachable = bfs(i);
if (reachable.size === n) result.push(i);
}
return result;
}
// Example usage:
const n = 6;
const edges = [[0,1],[0,2],[2,5],[3,4],[4,2]];
console.log(findSmallestSetOfVertices(n, edges));
Line Notes
const graph = Array.from({length: n}, () => []);Initialize adjacency list
for (const [u, v] of edges)Build graph edges
function bfs(start)Define BFS to find reachable nodes
const visited = new Set();Track visited nodes
const queue = [start];Initialize BFS queue
while (queue.length > 0)Process BFS queue
const node = queue.shift();Get current node
if (!visited.has(node))Process unvisited nodes
for (const nei of graph[node])Explore neighbors
if (!visited.has(nei)) queue.push(nei);Add unvisited neighbors to queue
const result = [];Store nodes that reach all others
for (let i = 0; i < n; i++)Check reachability from each node
const reachable = bfs(i);Get reachable nodes from node i
if (reachable.size === n) result.push(i);If all nodes reachable, add to result
return result;Return nodes that reach all others
TimeO(n * (n + e))
SpaceO(n + e)
For each of the n nodes, we perform a BFS/DFS that can visit up to all n nodes and edges e, resulting in O(n*(n+e)) time.
💡 For n=1000 and e=2000, this means about 3 million operations, which is too slow for large inputs.
Interview Verdict: TLE
This brute force approach is too slow for large graphs but helps understand the problem and why we need a better method.