Given an array arr[][] which contains the edges of a graph to be used to construct an undirected graph G with N nodes, the task is to find the maximum component size in the graph after each edge is added while constructing the graph.
Examples:
Input: N = 4, arr[][] = {{1, 2}, {3, 4}, {2, 3}}
Output: 2 2 4
Explanation:
Initially, the graph has 4 individual nodes 1, 2, 3 and 4.
After the first edge is added : 1 – 2, 3, 4 -> maximum component size = 2
After the second edge is added : 1 – 2, 3 – 4 -> maximum component size = 2
After the third edge is added : 1 – 2 – 3 – 4 -> maximum component size = 4
Input: N = 4, arr[][] = {{2, 3}, {1, 2}, {1, 5}, {2, 4}}
Output: 2 3 4 5
Naive Approach: The naive approach for this problem is to add the edges sequentially and at each step apply depth-first search algorithm to find the size of the largest component.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int dfs( int u, int visited[],
vector< int >* adj)
{
visited[u] = 1;
int size = 1;
for ( auto child : adj[u]) {
if (!visited[child])
size += dfs(child,
visited, adj);
}
return size;
}
void maxSize(vector<pair< int , int > > e,
int n)
{
vector< int > adj[n];
int visited[n];
vector< int > answer;
for ( auto edge : e) {
adj[edge.first - 1].push_back(
edge.second - 1);
adj[edge.second - 1].push_back(
edge.first - 1);
memset (visited, 0,
sizeof (visited));
int maxAns = 0;
for ( int i = 0; i < n; i++) {
if (!visited[i]) {
maxAns = max(maxAns,
dfs(i, visited, adj));
}
}
answer.push_back(maxAns);
}
for ( auto i : answer) {
cout << i << " " ;
}
}
int main()
{
int N = 4;
vector<pair< int , int > > E;
E.push_back(make_pair(1, 2));
E.push_back(make_pair(3, 4));
E.push_back(make_pair(2, 3));
maxSize(E, N);
return 0;
}
|
Java
import java.util.*;
@SuppressWarnings ( "unchecked" )
class GFG{
static class pair
{
int Key, Value;
pair( int Key, int Value)
{
this .Key = Key;
this .Value = Value;
}
}
static int dfs( int u, int []visited,
ArrayList []adj)
{
visited[u] = 1 ;
int size = 1 ;
for ( int child : (ArrayList<Integer>)adj[u])
{
if (visited[child] == 0 )
size += dfs(child,
visited, adj);
}
return size;
}
static void maxSize(ArrayList e,
int n)
{
ArrayList []adj = new ArrayList[n];
for ( int i = 0 ; i < n; i++)
{
adj[i] = new ArrayList();
}
int []visited = new int [n];
ArrayList answer = new ArrayList();
for (pair edge : (ArrayList<pair>)e)
{
adj[edge.Key - 1 ].add(
edge.Value - 1 );
adj[edge.Value - 1 ].add(
edge.Key - 1 );
Arrays.fill(visited, 0 );
int maxAns = 0 ;
for ( int i = 0 ; i < n; i++)
{
if (visited[i] == 0 )
{
maxAns = Math.max(maxAns,
dfs(i, visited, adj));
}
}
answer.add(maxAns);
}
for ( int i : (ArrayList<Integer>) answer)
{
System.out.print(i + " " );
}
}
public static void main(String[] args)
{
int N = 4 ;
ArrayList E = new ArrayList();
E.add( new pair( 1 , 2 ));
E.add( new pair( 3 , 4 ));
E.add( new pair( 2 , 3 ));
maxSize(E, N);
}
}
|
Python3
def dfs(u, visited, adj):
visited[u] = 1
size = 1
for child in adj[u]:
if (visited[child] = = 0 ):
size + = dfs(child, visited, adj)
return size
def maxSize(e, n):
adj = []
for i in range (n):
adj.append([])
visited = [ 0 ] * (n)
answer = []
for edge in e:
adj[edge[ 0 ] - 1 ].append(edge[ 1 ] - 1 )
adj[edge[ 1 ] - 1 ].append(edge[ 0 ] - 1 )
visited = [ 0 ] * (n)
maxAns = 0
for i in range (n):
if (visited[i] = = 0 ):
maxAns = max (maxAns, dfs(i, visited, adj))
answer.append(maxAns)
for i in answer:
print (i, " ", end = " ")
N = 4
E = []
E.append([ 1 , 2 ])
E.append([ 3 , 4 ])
E.append([ 2 , 3 ])
maxSize(E, N)
|
C#
using System;
using System.Collections;
using System.Collections.Generic;
class GFG{
static int dfs( int u, int []visited,
ArrayList []adj)
{
visited[u] = 1;
int size = 1;
foreach ( int child in adj[u])
{
if (visited[child] == 0)
size += dfs(child,
visited, adj);
}
return size;
}
static void maxSize(ArrayList e,
int n)
{
ArrayList []adj = new ArrayList[n];
for ( int i = 0; i < n; i++)
{
adj[i] = new ArrayList();
}
int []visited = new int [n];
ArrayList answer = new ArrayList();
foreach (KeyValuePair< int , int > edge in e)
{
adj[edge.Key - 1].Add(
edge.Value - 1);
adj[edge.Value - 1].Add(
edge.Key - 1);
Array.Fill(visited,0);
int maxAns = 0;
for ( int i = 0; i < n; i++)
{
if (visited[i] == 0)
{
maxAns = Math.Max(maxAns,
dfs(i, visited, adj));
}
}
answer.Add(maxAns);
}
foreach ( int i in answer)
{
Console.Write(i + " " );
}
}
public static void Main( string [] args)
{
int N = 4;
ArrayList E = new ArrayList();
E.Add( new KeyValuePair< int , int >(1, 2));
E.Add( new KeyValuePair< int , int >(3, 4));
E.Add( new KeyValuePair< int , int >(2, 3));
maxSize(E, N);
}
}
|
Javascript
<script>
function dfs(u, visited, adj)
{
visited[u] = 1;
let size = 1;
for (let child = 0; child < adj[u].length; child++)
{
if (visited[adj[u][child]] == 0)
{
size += dfs(adj[u][child], visited, adj);
}
}
return size;
}
function maxSize(e, n)
{
let adj = [];
for (let i = 0; i < n; i++)
{
adj.push([]);
}
let visited = new Array(n);
visited.fill(0);
let answer = [];
for (let edge = 0; edge < e.length; edge++)
{
adj[e[edge][0] - 1].push(e[edge][1] - 1);
adj[e[edge][1] - 1].push(e[edge][0] - 1);
visited.fill(0);
let maxAns = 0;
for (let i = 0; i < n; i++)
{
if (visited[i] == 0)
maxAns = Math.max(maxAns, dfs(i, visited, adj));
}
answer.push(maxAns);
}
for (let i = 0; i < answer.length; i++)
{
document.write(answer[i] + " " );
}
}
let N = 4;
let E = [];
E.push([1, 2]);
E.push([3, 4]);
E.push([2, 3]);
maxSize(E, N);
</script>
|
Time Complexity: O(|E| * N)
Efficient Approach: The idea is to use the concept of Disjoint Set (Union by rank and Path compression) to solve the problem more efficiently.
- Each node is initially a disjoint set within itself. As and when the edges are added, the disjoint sets are merged together forming larger components. In the disjoint set implementation, we will make the ranking system based on component sizes i.e when merging of two components is performed the larger component’s root will be considered the final root after the merge operation.
- One way to find the largest size component after each edge addition is to traverse the size array (size[i] represents the size of the component in which node ‘i’ belongs), but this is inefficient when the number of nodes in the graph is high.
- A more efficient way is to store the component sizes of all the root in some ordered data structure like sets.
- When two components are merged, all we need to do is remove the previous component sizes from the set and add the combined component size. So at each step, we would be able to find the largest component size in logarithmic complexity.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int par[100005];
int size[100005];
int root( int i)
{
if (par[i] == i)
return i;
else
return par[i] = root(par[i]);
}
void merge( int a, int b)
{
int p = root(a);
int q = root(b);
if (p == q)
return ;
if (size[p] > size[q])
swap(p, q);
par[p] = q;
size[q] += size[p];
}
void maxSize(vector<pair< int , int > > e, int n)
{
for ( int i = 1; i < n + 1; i++) {
par[i] = i;
size[i] = 1;
}
vector< int > answer;
multiset< int > compSizes;
for ( int i = 1; i <= n; i++)
compSizes.insert(size[i]);
for ( auto edge : e) {
if (root(edge.first) != root(edge.second)) {
int size1 = size[root(edge.first)];
int size2 = size[root(edge.second)];
compSizes.erase(compSizes.find(size1));
compSizes.erase(compSizes.find(size2));
merge(edge.first, edge.second);
compSizes.insert(size1 + size2);
}
answer.push_back(*compSizes.rbegin());
}
for ( int i = 0; i < answer.size(); i++) {
cout << answer[i] << " " ;
}
}
int main()
{
int N = 4;
vector<pair< int , int > > E;
E.push_back(make_pair(1, 2));
E.push_back(make_pair(3, 4));
E.push_back(make_pair(2, 3));
maxSize(E, N);
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class MyPair
{
private final int key;
private final int value;
public MyPair( int aKey, int aValue)
{
key = aKey;
value = aValue;
}
public int key() { return key; }
public int value() { return value; }
}
class GFG
{
static int [] par = new int [ 100005 ];
static int [] s = new int [ 100005 ];
static int root( int i)
{
if (par[i] == i)
return i;
else
return par[i] = root(par[i]);
}
static void merge( int a, int b)
{
int p = root(a);
int q = root(b);
if (p == q)
return ;
if (s[p] > s[q]){
int temp = p;
p = q;
q = temp;
}
par[p] = q;
s[q] += s[p];
}
static void maxSize(ArrayList<MyPair> e, int n)
{
for ( int i = 1 ; i < n + 1 ; i++) {
par[i] = i;
s[i] = 1 ;
}
ArrayList<Integer> answer = new ArrayList<Integer>();
ArrayList<Integer> compSizes = new ArrayList<Integer> ();
for ( int i = 1 ; i <= n; i++)
compSizes.add(s[i]);
for ( int i = 0 ; i < e.size(); i++){
MyPair edge = e.get(i);
if (root(edge.key()) != root(edge.value())) {
int size1 = s[root(edge.key())];
int size2 = s[root(edge.value())];
compSizes.remove(compSizes.indexOf(size1));
compSizes.remove(compSizes.indexOf(size2));
merge(edge.key(), edge.value());
compSizes.add(size1 + size2);
Collections.sort(compSizes);
}
answer.add(compSizes.get(compSizes.size() - 1 ));
}
for ( int i = 0 ; i < answer.size(); i++) {
System.out.print(answer.get(i) + " " );
}
}
public static void main(String[] args)
{
int N = 4 ;
ArrayList<MyPair> E = new ArrayList<MyPair>();
E.add( new MyPair( 1 , 2 ));
E.add( new MyPair( 3 , 4 ));
E.add( new MyPair( 2 , 3 ));
maxSize(E, N);
}
}
|
Python3
par = [ - 1 ] * 100005
size = [ - 1 ] * 100005
def root(i):
if (par[i] = = i):
return i
par[i] = root(par[i])
return par[i]
def merge(a, b):
p = root(a)
q = root(b)
if (p = = q):
return
if (size[p] > size[q]):
p,q = q,p
par[p] = q
size[q] + = size[p]
def maxSize(e, n):
for i in range ( 1 , n + 1 ):
par[i] = i
size[i] = 1
answer = []
compSizes = dict ()
for i in range ( 1 ,n + 1 ):
compSizes[size[i]] = compSizes.get(size[i], 0 ) + 1
for edge in e:
if (root(edge[ 0 ]) ! = root(edge[ 1 ])) :
size1 = size[root(edge[ 0 ])]
size2 = size[root(edge[ 1 ])]
compSizes[size1] - = 1
if compSizes[size1] = = 0 :
del compSizes[size1]
compSizes[size2] - = 1
if compSizes[size2] = = 0 :
del compSizes[size2]
merge(edge[ 0 ], edge[ 1 ])
compSizes[size1 + size2] = compSizes.get(size1 + size2, 0 ) + 1
answer.append( max (compSizes.keys()))
for i in range ( len (answer)) :
print (answer[i],end = ' ' )
if __name__ = = '__main__' :
N = 4
E = []
E.append(( 1 , 2 ))
E.append(( 3 , 4 ))
E.append(( 2 , 3 ))
maxSize(E, N)
|
C#
using System;
using System.Collections.Generic;
class Program
{
static int [] par = new int [100005];
static int [] size = new int [100005];
static int root( int i)
{
if (par[i] == i)
return i;
else
return par[i] = root(par[i]);
}
static void merge( int a, int b)
{
int p = root(a);
int q = root(b);
if (p == q)
return ;
if (size[p] > size[q])
{
int temp = p;
p = q;
q = temp;
}
par[p] = q;
size[q] += size[p];
}
static void maxSize(List<Tuple< int , int >> e, int n)
{
for ( int i = 1; i < n + 1; i++)
{
par[i] = i;
size[i] = 1;
}
List< int > answer = new List< int >();
SortedSet< int > compSizes = new SortedSet< int >();
for ( int i = 1; i <= n; i++)
compSizes.Add(size[i]);
foreach ( var edge in e)
{
if (root(edge.Item1) != root(edge.Item2))
{
int size1 = size[root(edge.Item1)];
int size2 = size[root(edge.Item2)];
compSizes.Remove(size1);
compSizes.Remove(size2);
merge(edge.Item1, edge.Item2);
compSizes.Add(size1 + size2);
}
answer.Add(compSizes.Max);
}
foreach ( int i in answer)
{
Console.Write(i + " " );
}
}
static void Main( string [] args)
{
int N = 4;
List<Tuple< int , int >> E = new List<Tuple< int , int >>();
E.Add(Tuple.Create(1, 2));
E.Add(Tuple.Create(3, 4));
E.Add(Tuple.Create(2, 3));
maxSize(E, N);
Console.ReadLine();
}
}
|
Javascript
const par = [];
const size = [];
function root(i) {
if (par[i] === i) {
return i;
}
else {
return (par[i] = root(par[i]));
}
}
function merge(a, b) {
let p = root(a);
let q = root(b);
if (p === q) {
return ;
}
if (size[p] > size[q]) {
[p, q] = [q, p];
}
par[p] = q;
size[q] += size[p];
}
function maxSize(e, n) {
for (let i = 1; i < n + 1; i++) {
par[i] = i;
size[i] = 1;
}
const answer = [];
const compSizes = new Set(size.slice(1, n + 1));
for (const [a, b] of e) {
if (root(a) !== root(b)) {
const size1 = size[root(a)];
const size2 = size[root(b)];
compSizes. delete (size1);
compSizes. delete (size2);
merge(a, b);
compSizes.add(size1 + size2);
}
answer.push(Math.max(...compSizes));
}
console.log(answer.join( " " ));
}
const N = 4;
const E = [
[1, 2],
[3, 4],
[2, 3],
];
maxSize(E, N);
|
Time Complexity: O(|E| * log(N))
Auxiliary Space: O(N)
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
13 Mar, 2023
Like Article
Save Article