Debugging challengeIntermediate
DFS that is quadratic for no reason
Scenario
This connected-components counter is textbook DFS, and it returns correct answers. Yet on a graph with 2 · 10^5 vertices and 2 · 10^5 edges it takes 40 seconds and uses gigabytes of memory, while the same algorithm in Python finishes in under a second. Nothing is wrong with the algorithm. Find the bug.
1#include <iostream>2#include <vector>3using namespace std;4 5void dfs(int u, vector<vector<int>> adj, vector<bool> visited) {6 visited[u] = true;7 for (int v : adj[u])8 if (!visited[v]) dfs(v, adj, visited);9}10 11int countComponents(int n, vector<vector<int>> adj) {12 vector<bool> visited(n, false);13 int components = 0;14 for (int u = 0; u < n; ++u) {15 if (!visited[u]) {16 ++components;17 dfs(u, adj, visited);18 }19 }20 return components;21}22 23int main() {24 int n = 5;25 vector<vector<int>> adj(n);26 auto add = [&](int a, int b) { adj[a].push_back(b); adj[b].push_back(a); };27 add(0, 1); add(1, 2); add(3, 4);28 for (auto row : adj) { for (int v : row) cout << v << ' '; cout << '\n'; }29 cout << countComponents(n, adj) << "\n"; // prints 5, expected 230}Your task
- The output is
5, not2. Explain why every vertex is counted as its own component even though the DFS runs. - Estimate how much data is copied per
dfscall, and the total work forV = E = 2 · 10^5. - Fix the signatures. Which parameters should be
const&, which&, and why? - There is a third, subtler copy in
main. Find it. - State the complexity before and after.
DebuggingOptimizationComplexity Analysis
Work it out
Write your analysis before revealing anything. The self-check below compares it against what a strong answer contains.
Reveal
Progressive — each section builds on the previous one.
The bug
Why it happens
The fix
Edge cases
Complexity
Self-check
Tick what your analysis covered. Be honest — this feeds your readiness profile.