Connected Components Using BFS in DSA C++ - Time & Space Complexity
We want to understand how the time needed to find connected parts in a graph grows as the graph gets bigger.
How does the work change when the number of nodes and edges increases?
Analyze the time complexity of the following code snippet.
void bfs(int start, vector<vector<int>>& graph, vector<bool>& visited) {
queue<int> q;
q.push(start);
visited[start] = true;
while (!q.empty()) {
int node = q.front();
q.pop();
for (int neighbor : graph[node]) {
if (!visited[neighbor]) {
visited[neighbor] = true;
q.push(neighbor);
}
}
}
}
int countConnectedComponents(vector<vector<int>>& graph) {
int n = graph.size();
vector<bool> visited(n, false);
int count = 0;
for (int i = 0; i < n; i++) {
if (!visited[i]) {
bfs(i, graph, visited);
count++;
}
}
return count;
}
This code finds how many separate groups of connected nodes exist in a graph using BFS.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Visiting each node and its neighbors once using BFS.
- How many times: Each node is visited once, and each edge is checked once during BFS.
As the graph grows, the BFS visits every node and edge once, so the work grows with the total nodes plus edges.
| Input Size (n nodes, m edges) | Approx. Operations |
|---|---|
| 10 nodes, 15 edges | About 25 visits (10 nodes + 15 edges) |
| 100 nodes, 200 edges | About 300 visits (100 + 200) |
| 1000 nodes, 5000 edges | About 6000 visits (1000 + 5000) |
Pattern observation: The total work grows roughly as the sum of nodes and edges, increasing linearly with graph size.
Time Complexity: O(n + m)
This means the time needed grows linearly with the number of nodes plus edges in the graph.
[X] Wrong: "BFS takes O(n²) time because it uses nested loops."
[OK] Correct: BFS visits each node and edge only once, so it does not repeatedly check all pairs, avoiding quadratic time.
Understanding BFS time complexity helps you explain how graph traversal scales, a key skill for many coding challenges and real-world problems.
"What if we used DFS instead of BFS? How would the time complexity change?"
Practice
Solution
Step 1: Understand BFS traversal in undirected graph
BFS explores all nodes reachable from a given start node by visiting neighbors level by level.Step 2: Connect BFS to connected components
All nodes visited during BFS from a start node belong to the same connected component.Final Answer:
All nodes reachable from a starting node forming one connected component -> Option DQuick Check:
BFS finds connected components = All nodes reachable from a starting node forming one connected component [OK]
- Confusing BFS with shortest path only
- Thinking BFS counts edges
- Mixing connected components with node degrees
Solution
Step 1: Understand vector<bool> usage for visited nodes
visited is a boolean vector indexed by node number; marking visited means setting visited[node] to true.Step 2: Identify correct syntax for assignment
Assigning true to visited[node] is done by visited[node] = true; other options are invalid or comparisons.Final Answer:
visited[node] = true; -> Option AQuick Check:
Mark visited with assignment = visited[node] = true; [OK]
- Using == instead of = for assignment
- Trying to push_back in a fixed-size vector
- Using insert which is for sets, not vectors
int n = 5;
vector adj = {{1}, {0, 2}, {1}, {4}, {3}};
vector<bool> visited(n, false);
int count = 0;
for (int i = 0; i < n; i++) {
if (!visited[i]) {
queue<int> q;
q.push(i);
visited[i] = true;
while (!q.empty()) {
int u = q.front(); q.pop();
for (int v : adj[u]) {
if (!visited[v]) {
visited[v] = true;
q.push(v);
}
}
}
count++;
}
}
cout << count << endl;Solution
Step 1: Analyze the graph adjacency list
Nodes 0,1,2 form one connected component (0 connected to 1, 1 connected to 2). Nodes 3 and 4 form another connected component (3 connected to 4).Step 2: Trace BFS and count connected components
Start BFS at node 0: visits 0,1,2 (component 1). Next unvisited node is 3: visits 3,4 (component 2). Total components = 2.Final Answer:
2 -> Option BQuick Check:
Two connected groups = 2 [OK]
- Counting edges instead of components
- Not marking visited correctly causing overcount
- Misreading adjacency list connections
int count = 0;
for (int i = 0; i < n; i++) {
if (visited[i]) {
queue<int> q;
q.push(i);
visited[i] = true;
while (!q.empty()) {
int u = q.front(); q.pop();
for (int v : adj[u]) {
if (!visited[v]) {
visited[v] = true;
q.push(v);
}
}
}
count++;
}Solution
Step 1: Check the condition to start BFS
The BFS should start only from unvisited nodes, so the condition must be if (!visited[i]). The code incorrectly starts BFS from visited nodes.Step 2: Understand impact of wrong condition
Starting BFS from visited nodes means some components won't be counted, causing incorrect count.Final Answer:
The condition should be if (!visited[i]) instead of if (visited[i]) -> Option AQuick Check:
Start BFS on unvisited nodes = The condition should be if (!visited[i]) instead of if (visited[i]) [OK]
- Starting BFS on visited nodes
- Misplacing count increment inside loop
- Incorrect queue scope causing logic errors
Solution
Step 1: Identify connected components from edges
Edges connect nodes into groups: {0,1,2}, {3,4}, {5,6} forming 3 components.Step 2: Determine BFS start nodes
BFS starts from the smallest unvisited node in each component: 0 for first, 3 for second, 5 for third.Final Answer:
Start nodes: 0, 3, 5; Total components: 3 -> Option CQuick Check:
3 components starting at 0,3,5 = Start nodes: 0, 3, 5; Total components: 3 [OK]
- Counting wrong number of components
- Starting BFS at nodes inside components instead of smallest
- Confusing edges with components count
Ready to prove it?
Pass the test and this pattern moves unknown
