Given an undirected graph(the graph may contain one or more components) represented by an adjacency list adj[][], return all the connected components in any order.
Examples:
Input: adj[][] = [[2, 3], [2], [0, 1], [0], [5], [4]]
Output: [[0, 1, 2, 3], [4, 5]]
Explanation: There are 2 different connected components. They are {0, 1, 2, 3} and {4, 5}.Input: adj[][] = [[1, 2], [0, 2], [0, 1, 3, 4], [2], [2]]
Output: [0, 1, 2, 3, 4]
Explanation: There is a single component, i.e., {0, 1, 2, 3, 4}.
Table of Content
[Approach 1]: Using Depth first search (DFS)
In this approach, we perform a DFS once for every connected component in the graph. Each DFS call starting from an unvisited node explores and marks all nodes belonging to that component. Hence, for each DFS call, we can store the nodes of that component.
//Driver Code Starts
#include <iostream>
#include <vector>
using namespace std;
//Driver Code Ends
void dfs(vector<vector<int>>& adj, vector<bool>& visited, int s, vector<int>& res) {
visited[s] = true;
res.push_back(s);
// Recursively visit all adjacent
// vertices that are not visited yet
for (int i : adj[s]) {
if (!visited[i]) {
dfs(adj, visited, i, res);
}
}
}
vector<vector<int>> getComponents(vector<vector<int>>& adj) {
int V = adj.size();
vector<bool> visited(V, false);
vector<vector<int>> res;
// Loop through all vertices
// to handle all components
for (int i = 0; i < V; i++) {
if (!visited[i]) {
vector<int> component;
dfs(adj, visited, i, component);
res.push_back(component);
}
}
return res;
}
//Driver Code Starts
void addEdge(vector<vector<int>>& adj, int u, int v) {
adj[u].push_back(v);
adj[v].push_back(u);
}
int main() {
int V = 6;
vector<vector<int>> adj(V);
// creating adjacency list
addEdge(adj, 1, 2);
addEdge(adj, 0, 3);
addEdge(adj, 2, 0);
addEdge(adj, 5, 4);
// Perform DFS
vector<vector<int>> res = getComponents(adj);
for (auto& component : res) {
for (int vertex : component) {
cout << vertex << " ";
}
cout << endl;
}
return 0;
}
//Driver Code Ends
//Driver Code Starts
import java.util.ArrayList;
public class GFG {
//Driver Code Ends
private static void
dfs(ArrayList<ArrayList<Integer>> adj,
boolean[] visited, int s, ArrayList<Integer> res) {
visited[s] = true;
res.add(s);
// Recursively visit all adjacent
// vertices that are not visited yet
for (int i : adj.get(s)) {
if (!visited[i]) {
dfs(adj, visited, i, res);
}
}
}
public static ArrayList<ArrayList<Integer>>
getComponents(ArrayList<ArrayList<Integer>> adj) {
boolean[] visited = new boolean[adj.size()];
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
// Loop through all vertices
// to handle all components
for (int i = 0; i < adj.size(); i++) {
if (!visited[i]) {
ArrayList<Integer> component = new ArrayList<>();
dfs(adj, visited, i, component);
res.add(component);
}
}
return res;
}
//Driver Code Starts
static void addEdge(ArrayList<ArrayList<Integer>> adj, int u, int v) {
adj.get(u).add(v);
adj.get(v).add(u);
}
public static void main(String[] args) {
int V = 6;
ArrayList<ArrayList<Integer>> adj = new ArrayList<>();
// creating adjacency list
for (int i = 0; i < V; i++)
adj.add(new ArrayList<>());
addEdge(adj, 1, 2);
addEdge(adj, 0, 3);
addEdge(adj, 2, 0);
addEdge(adj, 5, 4);
// Perform DFS
ArrayList<ArrayList<Integer>> res = getComponents(adj);
for (ArrayList<Integer> component : res) {
for (int vertex : component) {
System.out.print(vertex + " ");
}
System.out.println();
}
}
}
//Driver Code Ends
#Driver Code Starts
from collections import defaultdict
#Driver Code Ends
def dfs(adj, visited, s, res):
visited[s] = True
res.append(s)
# Recursively visit all adjacent
# vertices that are not visited yet
for i in adj[s]:
if not visited[i]:
dfs(adj, visited, i, res)
def getComponents(adj):
V = len(adj)
visited = [False] * V
res = []
# Loop through all vertices
# to handle all components
for i in range(V):
if not visited[i]:
component = []
dfs(adj, visited, i, component)
res.append(component)
return res
#Driver Code Starts
def addEdge(adj, u, v):
adj[u].append(v)
adj[v].append(u)
if __name__ == "__main__":
V = 6
adj = []
# creating adjacency list
for i in range(V):
adj.append([])
addEdge(adj, 1, 2)
addEdge(adj, 0, 3)
addEdge(adj, 2, 0)
addEdge(adj, 5, 4)
# Perform DFS
res = getComponents(adj)
for component in res:
for vertex in component:
print(vertex, end=" ")
print()
#Driver Code Ends
//Driver Code Starts
using System;
using System.Collections.Generic;
class GFG {
//Driver Code Ends
private static void dfs(List<List<int>> adj, bool[] visited, int s, List<int> res) {
visited[s] = true;
res.Add(s);
// Recursively visit all adjacent
// vertices that are not visited yet
foreach (int i in adj[s]) {
if (!visited[i]) {
dfs(adj, visited, i, res);
}
}
}
public static List<List<int>> getComponents(List<List<int>> adj) {
int V = adj.Count;
bool[] visited = new bool[V];
List<List<int>> res = new List<List<int>>();
// Loop through all vertices
// to handle all components
for (int i = 0; i < V; i++) {
if (!visited[i]) {
List<int> component = new List<int>();
dfs(adj, visited, i, component);
res.Add(component);
}
}
return res;
}
//Driver Code Starts
static void addEdge(List<List<int>> adj, int u, int v) {
adj[u].Add(v);
adj[v].Add(u);
}
static void Main() {
int V = 6;
List<List<int>> adj = new List<List<int>>();
// creating adjacency list
for (int i = 0; i < V; i++)
adj.Add(new List<int>());
addEdge(adj, 1, 2);
addEdge(adj, 0, 3);
addEdge(adj, 2, 0);
addEdge(adj, 5, 4);
// Perform DFS
List<List<int>> res = getComponents(adj);
foreach (List<int> component in res) {
foreach (int vertex in component) {
Console.Write(vertex + " ");
}
Console.WriteLine();
}
}
}
//Driver Code Ends
function dfs(adj, visited, s, res) {
visited[s] = true;
res.push(s);
// Recursively visit all adjacent
// vertices that are not visited yet
for (let i of adj[s]) {
if (!visited[i]) {
dfs(adj, visited, i, res);
}
}
}
function getComponents(adj) {
const V = adj.length;
const visited = new Array(V).fill(false);
const res = [];
// Loop through all vertices
// to handle all components
for (let i = 0; i < V; i++) {
if (!visited[i]) {
const component = [];
dfs(adj, visited, i, component);
res.push(component);
}
}
return res;
}
//Driver Code Starts
function addEdge(adj, u, v) {
adj[u].push(v);
adj[v].push(u);
}
// Driver code
let V = 6;
let adj = [];
// creating adjacency list
for (let i = 0; i < V; i++)
adj.push([]);
addEdge(adj, 1, 2);
addEdge(adj, 0, 3);
addEdge(adj, 2, 0);
addEdge(adj, 5, 4);
// Perform DFS
const res = getComponents(adj);
for (const component of res) {
console.log(component.join(" "));
}
//Driver Code Ends
Output
0 3 2 1 4 5
Time complexity: O(V + E). We visit every vertex at most once and every edge is traversed at most once.
Auxiliary Space: O(V + E), since an extra visited array of size V is required, and recursive stack size.
[Approach 2]: Using Breadth first search (BFS) - O(V+E) Time and O(V) Space
The main idea is to perform a BFS once for every connected component in the graph. Each BFS call starting from an unvisited node explores and marks all nodes belonging to that component. Hence, for each BFS call, we can store the nodes of that component.
//Driver Code Starts
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
//Driver Code Ends
// BFS for a single connected component
void bfs(vector<vector<int>>& adj, int src, vector<bool>& visited, vector<int>& res) {
queue<int> q;
visited[src] = true;
q.push(src);
while (!q.empty()) {
int curr = q.front();
q.pop();
res.push_back(curr);
// visit all the unvisited
// neighbours of current node
for (int x : adj[curr]) {
if (!visited[x]) {
visited[x] = true;
q.push(x);
}
}
}
}
// BFS for all components (handles disconnected graphs)
vector<vector<int>> getComponents(vector<vector<int>>& adj) {
int V = adj.size();
vector<bool> visited(V, false);
vector<vector<int>> res;
for (int i = 0; i < V; i++) {
if (!visited[i]) {
vector<int> component;
bfs(adj, i, visited, component);
res.push_back(component);
}
}
return res;
}
//Driver Code Starts
void addEdge(vector<vector<int>>& adj, int u, int v) {
adj[u].push_back(v);
adj[v].push_back(u);
}
int main() {
int V = 6;
vector<vector<int>> adj(V);
// creating adjacency list
addEdge(adj, 1, 2);
addEdge(adj, 0, 3);
addEdge(adj, 2, 0);
addEdge(adj, 5, 4);
vector<vector<int>> res = getComponents(adj);
for (auto& component : res) {
for (int vertex : component) {
cout << vertex << " ";
}
cout << endl;
}
return 0;
}
//Driver Code Ends
//Driver Code Starts
import java.util.ArrayList;
import java.util.Queue;
import java.util.LinkedList;
class GfG {
//Driver Code Ends
// BFS for a single connected component
static void bfs(ArrayList<ArrayList<Integer>> adj, int src, boolean[] visited, ArrayList<Integer> res) {
Queue<Integer> q = new LinkedList<>();
visited[src] = true;
q.add(src);
while (!q.isEmpty()) {
int curr = q.poll();
res.add(curr);
// visit all the unvisited
// neighbours of current node
for (int x : adj.get(curr)) {
if (!visited[x]) {
visited[x] = true;
q.add(x);
}
}
}
}
// BFS for all components (handles disconnected graphs)
static ArrayList<ArrayList<Integer>> getComponents(ArrayList<ArrayList<Integer>> adj) {
int V = adj.size();
boolean[] visited = new boolean[V];
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
for (int i = 0; i < V; i++) {
if (!visited[i]) {
ArrayList<Integer> component = new ArrayList<>();
bfs(adj, i, visited, component);
res.add(component);
}
}
return res;
}
//Driver Code Starts
static void addEdge(ArrayList<ArrayList<Integer>> adj, int u, int v) {
adj.get(u).add(v);
adj.get(v).add(u);
}
public static void main(String[] args) {
int V = 6;
ArrayList<ArrayList<Integer>> adj = new ArrayList<>();
// creating adjacency list
for (int i = 0; i < V; i++)
adj.add(new ArrayList<>());
addEdge(adj, 1, 2);
addEdge(adj, 0, 3);
addEdge(adj, 2, 0);
addEdge(adj, 5, 4);
ArrayList<ArrayList<Integer>> res = getComponents(adj);
for (ArrayList<Integer> component : res) {
for (int vertex : component) {
System.out.print(vertex + " ");
}
System.out.println();
}
}
}
//Driver Code Ends
#Driver Code Starts
from collections import deque
#Driver Code Ends
# BFS for a single connected component
def bfs(adj, src, visited, res):
q = deque()
visited[src] = True
q.append(src)
while q:
curr = q.popleft()
res.append(curr)
# visit all the unvisited
# neighbours of current node
for x in adj[curr]:
if not visited[x]:
visited[x] = True
q.append(x)
# BFS for all components (handles disconnected graphs)
def getComponents(adj):
V = len(adj)
visited = [False] * V
res = []
# Loop through all vertices
# to handle all components
for i in range(V):
if not visited[i]:
component = []
bfs(adj, i, visited, component)
res.append(component)
return res
#Driver Code Starts
def addEdge(adj, u, v):
adj[u].append(v)
adj[v].append(u)
if __name__ == "__main__":
V = 6
adj = []
# creating adjacency list
for i in range(V):
adj.append([])
addEdge(adj, 1, 2)
addEdge(adj, 0, 3)
addEdge(adj, 2, 0)
addEdge(adj, 5, 4)
# Perform BFS
res = getComponents(adj)
for component in res:
for vertex in component:
print(vertex, end=" ")
print()
#Driver Code Ends
//Driver Code Starts
using System;
using System.Collections.Generic;
class GFG {
//Driver Code Ends
// BFS for a single connected component
private static void bfs(List<List<int>> adj,
int src, bool[] visited, List<int> res) {
Queue<int> q = new Queue<int>();
visited[src] = true;
q.Enqueue(src);
while (q.Count > 0) {
int curr = q.Dequeue();
res.Add(curr);
// visit all the unvisited
// neighbours of current node
foreach (int x in adj[curr]) {
if (!visited[x]) {
visited[x] = true;
q.Enqueue(x);
}
}
}
}
// BFS for all components (handles disconnected graphs)
public static List<List<int>> getComponents(List<List<int>> adj) {
int V = adj.Count;
bool[] visited = new bool[V];
List<List<int>> res = new List<List<int>>();
for (int i = 0; i < V; i++) {
if (!visited[i]) {
List<int> component = new List<int>();
bfs(adj, i, visited, component);
res.Add(component);
}
}
return res;
}
//Driver Code Starts
static void addEdge(List<List<int>> adj, int u, int v) {
adj[u].Add(v);
adj[v].Add(u);
}
static void Main() {
int V = 6;
List<List<int>> adj = new List<List<int>>();
// creating adjacency list
for (int i = 0; i < V; i++)
adj.Add(new List<int>());
addEdge(adj, 1, 2);
addEdge(adj, 0, 3);
addEdge(adj, 2, 0);
addEdge(adj, 5, 4);
List<List<int>> res = getComponents(adj);
foreach (List<int> component in res) {
foreach (int vertex in component) {
Console.Write(vertex + " ");
}
Console.WriteLine();
}
}
}
//Driver Code Ends
// BFS for a single connected component
function bfs(adj, src, visited, res) {
const q = [];
visited[src] = true;
q.push(src);
while (q.length > 0) {
const curr = q.shift();
res.push(curr);
// visit all the unvisited
// neighbours of current node
for (const x of adj[curr]) {
if (!visited[x]) {
visited[x] = true;
q.push(x);
}
}
}
}
// BFS for all components (handles disconnected graphs)
function getComponents(adj) {
const V = adj.length;
const visited = new Array(V).fill(false);
const res = [];
// Loop through all vertices
// to handle all components
for (let i = 0; i < V; i++) {
if (!visited[i]) {
const component = [];
bfs(adj, i, visited, component);
res.push(component);
}
}
return res;
}
//Driver Code Starts
function addEdge(adj, u, v) {
adj[u].push(v);
adj[v].push(u);
}
// Driver code
let V = 6;
let adj = [];
// creating adjacency list
for (let i = 0; i < V; i++)
adj.push([]);
addEdge(adj, 1, 2);
addEdge(adj, 0, 3);
addEdge(adj, 2, 0);
addEdge(adj, 5, 4);
// Perform BFS
const res = getComponents(adj);
for (const component of res) {
console.log(component.join(" "));
}
//Driver Code Ends
Output
0 3 2 1 4 5
[Approach 3]: Using Disjoint Set Union (DSU) - O(V+E) Time and O(V) Space
The idea is to use Disjoint Set Union (DSU) to find all connected components in the graph. We unite the vertices connected by edges using union function and finally we get different vertices belonging to different components.
//Driver Code Starts
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
//Driver Code Ends
// DSU class
class DSU {
public:
vector<int> parent;
DSU(int n) {
parent.resize(n);
// Each node is its own parent initially
for (int i = 0; i < n; i++) parent[i] = i;
}
// Find with path compression
int findParent(int u) {
if (u == parent[u]) return u;
return parent[u] = findParent(parent[u]);
}
// Union the sets of u and v
void unite(int u, int v) {
int pu = findParent(u);
int pv = findParent(v);
if (pu == pv) return;
parent[pu] = pv;
}
};
// Function to find all connected components using DSU
vector<vector<int>> getComponents(vector<vector<int>>& adj) {
int V = adj.size();
DSU dsu(V);
// unite components on the basis of edges
for (int i = 0; i < V; i++) {
for (int next : adj[i]) {
dsu.unite(i, next);
}
}
unordered_map<int, vector<int>> resMap;
for (int i = 0; i < V; i++) {
int par = dsu.findParent(i);
resMap[par].push_back(i);
}
vector<vector<int>> res;
for (auto& [p, nodes] : resMap)
res.push_back(nodes);
return res;
}
//Driver Code Starts
void addEdge(vector<vector<int>>& adj, int u, int v) {
adj[u].push_back(v);
adj[v].push_back(u);
}
int main() {
int V = 6;
vector<vector<int>> adj(V);
// creating adjacency list
addEdge(adj, 1, 2);
addEdge(adj, 0, 3);
addEdge(adj, 2, 0);
addEdge(adj, 5, 4);
vector<vector<int>> res = getComponents(adj);
for (auto& component : res) {
for (int vertex : component) {
cout << vertex << " ";
}
cout << endl;
}
return 0;
}
//Driver Code Ends
//Driver Code Starts
import java.util.*;
//Driver Code Ends
// DSU class
class DSU {
int[] parent;
public DSU(int n) {
parent = new int[n];
// Each node is its own parent initially
for (int i = 0; i < n; i++) {
parent[i] = i;
}
}
// Find with path compression
int findParent( int u ) {
if( u == parent[u]) return u;
return parent[u] = findParent(parent[u]);
}
// Union the sets of u and v
void unite( int u, int v ) {
int pu = findParent(u);
int pv = findParent(v);
if( pu == pv ) return;
parent[pu] = pv;
}
}
class GFG {
// Function to find all connected components using DSU
static ArrayList<ArrayList<Integer>> getComponents(ArrayList<ArrayList<Integer>> adj) {
int V = adj.size();
DSU dsu = new DSU(V);
for( int i = 0; i < V; i++ ) {
for( int next : adj.get(i)) {
dsu.unite(i, next);
}
}
Map<Integer, ArrayList<Integer>> resMap = new HashMap<>();
// unite components on the basis of edges
for( int i = 0; i < V; i++ ) {
resMap.computeIfAbsent(dsu.findParent(i),
k -> new ArrayList<>()).add(i);
}
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
for( int par : resMap.keySet()) {
res.add(resMap.get(par));
}
return res;
}
//Driver Code Starts
static void addEdge(ArrayList<ArrayList<Integer>> adj, int u, int v) {
adj.get(u).add(v);
adj.get(v).add(u);
}
public static void main(String[] args) {
int V = 6;
ArrayList<ArrayList<Integer>> adj = new ArrayList<>();
// creating adjacency list
for (int i = 0; i < V; i++)
adj.add(new ArrayList<>());
addEdge(adj, 1, 2);
addEdge(adj, 0, 3);
addEdge(adj, 2, 0);
addEdge(adj, 5, 4);
ArrayList<ArrayList<Integer>> res = getComponents(adj);
for (ArrayList<Integer> component : res) {
for (int vertex : component) {
System.out.print(vertex + " ");
}
System.out.println();
}
}
}
//Driver Code Ends
# DSU class
class DSU:
def __init__(self, n):
self.parent = [i for i in range(n)] # Each node is its own parent initially
# Find with path compression
def find_parent(self, u):
if u == self.parent[u]:
return u
self.parent[u] = self.find_parent(self.parent[u])
return self.parent[u]
# Union the sets of u and v
def unite(self, u, v):
pu = self.find_parent(u)
pv = self.find_parent(v)
if pu == pv:
return
self.parent[pu] = pv
# Function to find all connected components using DSU
def getComponents(adj):
V = len(adj)
dsu = DSU(V)
# unite components on the basis of edges
for i in range(V):
for nxt in adj[i]:
dsu.unite(i, nxt)
res_map = {}
for i in range(V):
par = dsu.find_parent(i)
res_map.setdefault(par, []).append(i)
res = list(res_map.values())
return res
#Driver Code Starts
def addEdge(adj, u, v):
adj[u].append(v)
adj[v].append(u)
if __name__ == "__main__":
V = 6
adj = []
# creating adjacency list
for i in range(V):
adj.append([])
addEdge(adj, 1, 2)
addEdge(adj, 0, 3)
addEdge(adj, 2, 0)
addEdge(adj, 5, 4)
# Perform BFS
res = getComponents(adj)
for component in res:
for vertex in component:
print(vertex, end=" ")
print()
#Driver Code Ends
//Driver Code Starts
using System;
using System.Collections.Generic;
//Driver Code Ends
// DSU class
class DSU {
int[] parent;
public DSU(int n) {
parent = new int[n];
// Each node is its own parent initially
for (int i = 0; i < n; i++)
parent[i] = i;
}
// Find with path compression
int findParent(int u) {
if (u == parent[u]) return u;
return parent[u] = findParent(parent[u]);
}
// Union the sets of u and v
public void unite(int u, int v) {
int pu = findParent(u);
int pv = findParent(v);
if (pu == pv) return;
parent[pu] = pv;
}
public int getParent(int u) => findParent(u);
}
class GFG {
// Function to find all connected components using DSU
static List<List<int>> getComponents(List<List<int>> adj) {
int V = adj.Count;
DSU dsu = new DSU(V);
for (int i = 0; i < V; i++) {
foreach (int next in adj[i])
dsu.unite(i, next);
}
Dictionary<int, List<int>> resMap = new Dictionary<int, List<int>>();
// unite components on the basis of edges
for (int i = 0; i < V; i++) {
int par = dsu.getParent(i);
if (!resMap.ContainsKey(par))
resMap[par] = new List<int>();
resMap[par].Add(i);
}
List<List<int>> res = new List<List<int>>();
foreach (var kv in resMap.Values)
res.Add(kv);
return res;
}
//Driver Code Starts
static void addEdge(List<List<int>> adj, int u, int v) {
adj[u].Add(v);
adj[v].Add(u);
}
static void Main() {
int V = 6;
List<List<int>> adj = new List<List<int>>();
// creating adjacency list
for (int i = 0; i < V; i++)
adj.Add(new List<int>());
addEdge(adj, 1, 2);
addEdge(adj, 0, 3);
addEdge(adj, 2, 0);
addEdge(adj, 5, 4);
List<List<int>> res = getComponents(adj);
foreach (List<int> component in res) {
foreach (int vertex in component) {
Console.Write(vertex + " ");
}
Console.WriteLine();
}
}
}
//Driver Code Ends
// DSU class
class DSU {
constructor(n) {
this.parent = Array.from({ length: n }, (_, i) => i);
}
// Find with path compression
findParent(u) {
if (u === this.parent[u]) return u;
return (this.parent[u] = this.findParent(this.parent[u]));
}
// Union the sets of u and v
unite(u, v) {
const pu = this.findParent(u);
const pv = this.findParent(v);
if (pu === pv) return;
this.parent[pu] = pv;
}
}
// Function to find all connected components using DSU
function getComponents(adj) {
const V = adj.length;
const dsu = new DSU(V);
for (let i = 0; i < V; i++) {
for (const next of adj[i]) {
dsu.unite(i, next);
}
}
const resMap = new Map();
// unite components on the basis of edges
for (let i = 0; i < V; i++) {
const par = dsu.findParent(i);
if (!resMap.has(par)) resMap.set(par, []);
resMap.get(par).push(i);
}
return Array.from(resMap.values());
}
//Driver Code Starts
function addEdge(adj, u, v) {
adj[u].push(v);
adj[v].push(u);
}
// Driver code
let V = 6;
let adj = [];
// creating adjacency list
for (let i = 0; i < V; i++)
adj.push([]);
addEdge(adj, 1, 2);
addEdge(adj, 0, 3);
addEdge(adj, 2, 0);
addEdge(adj, 5, 4);
// Perform BFS
const res = getComponents(adj);
for (const component of res) {
console.log(component.join(" "));
}
//Driver Code Ends
Output
4 5 0 1 2 3

