Graphs · Easy

186. Count Connected Components in an Undirected Graph

Topics: Graph

Solve it on DeVert Campus - free code runner

Problem

Given an undirected graph with n vertices and m edges, count the number of connected components (an isolated vertex with no edges counts as its own component).

Input and output

Input: The first line contains n, the number of vertices. The second line contains m, the number of edges. Each of the next m lines contains two integers, an undirected edge. Output: Print a single integer - the number of connected components.

Example

Input:
5
2
0 1
1 2
Output:
2

Constraints

1 <= n <= 10^5

Key observation

An ISOLATED vertex with zero edges still counts as its OWN separate component - a small but important detail explicitly called out in this problem's own statement.

Intuition

Count how many separate, disconnected groups (components) a graph splits into. Brute force: Check every pair of vertices directly for reachability - this costs O(n²) or worse, far more than necessary when a single BFS/DFS sweep answers the question directly. Optimised: Since one BFS/DFS run from any vertex reaches EXACTLY its entire connected component, repeating this only from vertices not yet covered by a previous run visits every vertex exactly once overall, with the number of times you START a fresh run being exactly the component count.

Approach 1

Represent the graph as an n x n adjacency matrix, so finding a vertex's neighbors during a traversal requires scanning its entire matrix row. Running a DFS or BFS from every unvisited vertex this way still correctly finds every component, but each neighbor lookup costs O(n) instead of being handed directly from an adjacency list. Time: O(n^2) Space: O(n^2)

Optimal - Union-Find (DSU)

Use a Disjoint Set Union structure with path compression and union by rank/size: start with n separate sets, then union the sets containing each edge's two endpoints for all m edges. The final number of distinct set representatives (roots) is the answer. This avoids recursive or stack-based traversal entirely, eliminating any risk of stack overflow on deep graphs, and each union/find operation runs in near-constant amortized time. Time: O((n + m) * alpha(n)) Space: O(n)

Better - Adjacency List + DFS/BFS

Build an adjacency list from the m edges, then repeatedly pick any unvisited vertex, run a DFS or BFS from it to mark every vertex reachable from it, and increment a component counter each time a new search is started. Using an adjacency list means each edge is examined only a constant number of times overall rather than paying O(n) per neighbor lookup, so the traversal cost drops to the size of the graph itself. Time: O(n + m) Space: O(n + m)

Step by step

1. Run a BFS or DFS from every vertex that HASN'T been visited yet. 2. Every vertex reached during that traversal gets marked visited. 3. Each time you START a fresh traversal from an unvisited vertex, that's one more connected component.

Complexity

Time: O(n + m) - every vertex and edge is examined exactly once across all the BFS/DFS runs combined. Space: O(n), for the visited-tracking array.

Edge cases

Test m = 0 (every vertex is its own component, so the answer equals n), a fully connected graph (answer 1), and n at the upper bound of 10^5.

Interview tip

Be ready to mention Union-Find (Disjoint Set) as an equally valid alternative approach - processing all edges with union operations and counting the final number of distinct sets gives the same answer, often preferred when edges arrive incrementally.

All DSA problems