Difference between Smallest and Largest Component of the graph after each Query.
Last Updated :
07 Nov, 2023
Given an integer N, denoting the total number of nodes in a graph without any edges, you have to process Q queries of the form u, v denoting that you have to add an edge between node u and v, after each query you have to print the size difference between largest component and the smallest component of the graph.
Examples:
Input: N = 2, Q = 1, queries = [[1, 2]]
Output: 0
Explanation:
- Initial components = {{1}{2}}
- After query[0]:
- we have components = {{1, 2}}, Since we have only one component of size 2, the difference is 2-2 = 0.
Input: N = 4, Q = 2, queries = [[1, 2],[2, 4]]
Output: [1, 2]
Explanation:
- Initial components = {{1},{2},{3},{4}},
- After query[0]:
- we have components = {{1, 2},{3},{4}} , So difference is, 2-1 = 1.
- After query[1]:
- we have components = {{1, 2, 4},{3}} , So difference is, 3-1 = 2.
Approach: We can use Disjoint-Set-Union(DSU) and Priority Queue(using multiset) to solve this question as discussed below:
For each query of adding an edge between ‘u‘ and ‘v’ we can use DSU to put both the nodes in the same set and update the size of the set they are in. Now we can put this new size in our multiset and remove the older sizes from it.
Simply print the difference between the maximum and minimum element of the multiset to get the answer for each query.
Firstly we have to construct our DSU functions as per the below steps:
- Create a parent array of the size N i.e. the total number of nodes. This array will denote the parent of each node(component).
- make(int i): Initialize parent[i]=i, sizez[i]=1, and for each i insert 1 inside a multiset ‘st’. This indicates that each node currently has size 1 and forms a component of its own.
- find(int v): finds the parent of the component the node ‘v‘ belongs to.
- Union(int a, int b): Merge the nodes ‘a‘ and ‘b‘ together. Delete the old sizes of ‘a‘ and ‘b‘ from the ‘st’ and insert the new size formed by the combination of ‘a‘ and ‘b‘
Now use the below algorithm to solve the problem:
- Initialize the DSU data structure for each node from 1 to N, using the make function.
- For each query, Union the nodes u and v.
- Print the difference between the back and front element of the ‘st‘.
below is the implementation of the above algorithm:
C++
#include <bits/stdc++.h>
using namespace std;
int parent[1000];
int sizes[1000];
multiset< int > st;
void make( int i)
{
parent[i] = i;
sizes[i] = 1;
st.insert(1);
}
int find( int v)
{
if (v == parent[v])
return v;
return parent[v] = find(parent[v]);
}
void Union( int a, int b)
{
a = find(a);
b = find(b);
if (a != b) {
if (sizes[a] < sizes[b])
swap(a, b);
parent[b] = a;
st.erase(st.find(sizes[a]));
st.erase(st.find(sizes[b]));
st.insert(sizes[a] + sizes[b]);
sizes[a] += sizes[b];
}
}
int main()
{
int N = 4;
int Q = 2;
for ( int i = 1; i <= N; i++) {
make(i);
}
vector<vector< int > > queries = { { 1, 2 }, { 2, 4 } };
for ( int i = 0; i < Q; i++) {
int u = queries[i][0];
int v = queries[i][1];
Union(u, v);
int a = *st.begin();
int b = *(--st.end());
cout << b - a << endl;
}
}
|
Java
import java.util.*;
public class GFG {
static int [] parent = new int [ 1000 ];
static int [] sizes = new int [ 1000 ];
static List<Integer> st = new ArrayList<>();
static void make( int i) {
parent[i] = i;
sizes[i] = 1 ;
st.add( 1 );
}
static int find( int v) {
if (v == parent[v]) {
return v;
}
parent[v] = find(parent[v]);
return parent[v];
}
static void union( int a, int b) {
a = find(a);
b = find(b);
if (a != b) {
if (sizes[a] < sizes[b]) {
int temp = a;
a = b;
b = temp;
}
parent[b] = a;
st.remove(Integer.valueOf(sizes[a]));
st.remove(Integer.valueOf(sizes[b]));
st.add(sizes[a] + sizes[b]);
sizes[a] += sizes[b];
}
}
public static void main(String[] args) {
int N = 4 ;
int Q = 2 ;
for ( int i = 1 ; i <= N; i++) {
make(i);
}
int [][] queries = {{ 1 , 2 }, { 2 , 4 }};
for ( int i = 0 ; i < Q; i++) {
int u = queries[i][ 0 ];
int v = queries[i][ 1 ];
union(u, v);
int a = Collections.min(st);
int b = Collections.max(st);
System.out.println(b - a);
}
}
}
|
Python3
parent = [ 0 ] * 1000
sizes = [ 0 ] * 1000
st = []
def make(i):
parent[i] = i
sizes[i] = 1
st.append( 1 )
def find(v):
if v = = parent[v]:
return v
parent[v] = find(parent[v])
return parent[v]
def union(a, b):
a = find(a)
b = find(b)
if a ! = b:
if sizes[a] < sizes[b]:
a, b = b, a
parent[b] = a
st.remove(sizes[a])
st.remove(sizes[b])
st.append(sizes[a] + sizes[b])
sizes[a] + = sizes[b]
if __name__ = = "__main__" :
N = 4
Q = 2
for i in range ( 1 , N + 1 ):
make(i)
queries = [[ 1 , 2 ], [ 2 , 4 ]]
for i in range (Q):
u = queries[i][ 0 ]
v = queries[i][ 1 ]
union(u, v)
a = min (st)
b = max (st)
print (b - a)
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
public class GFG
{
static int [] parent = new int [1000];
static int [] sizes = new int [1000];
static List< int > st = new List< int >();
static void Make( int i)
{
parent[i] = i;
sizes[i] = 1;
st.Add(1);
}
static int Find( int v)
{
if (v == parent[v])
{
return v;
}
parent[v] = Find(parent[v]);
return parent[v];
}
static void Union( int a, int b)
{
a = Find(a);
b = Find(b);
if (a != b)
{
if (sizes[a] < sizes[b])
{
int temp = a;
a = b;
b = temp;
}
parent[b] = a;
st.Remove(sizes[a]);
st.Remove(sizes[b]);
st.Add(sizes[a] + sizes[b]);
sizes[a] += sizes[b];
}
}
public static void Main( string [] args)
{
int N = 4;
int Q = 2;
for ( int i = 1; i <= N; i++)
{
Make(i);
}
int [][] queries = new int [][] { new int [] { 1, 2 }, new int [] { 2, 4 } };
for ( int i = 0; i < Q; i++)
{
int u = queries[i][0];
int v = queries[i][1];
Union(u, v);
int a = st.Min();
int b = st.Max();
Console.WriteLine(b - a);
}
}
}
|
Javascript
const parent = new Array(1000);
for (let i = 0; i < parent.length; i++) {
parent[i] = i;
}
const sizes = new Array(1000).fill(1);
const st = [];
function make(i) {
parent[i] = i;
sizes[i] = 1;
st.push(1);
}
function find(v) {
if (v === parent[v]) {
return v;
}
parent[v] = find(parent[v]);
return parent[v];
}
function union(a, b) {
a = find(a);
b = find(b);
if (a !== b) {
if (sizes[a] < sizes[b]) {
[a, b] = [b, a];
}
parent[b] = a;
st.splice(st.indexOf(sizes[a]), 1);
st.splice(st.indexOf(sizes[b]), 1);
st.push(sizes[a] + sizes[b]);
sizes[a] += sizes[b];
}
}
function main() {
const N = 4;
const Q = 2;
for (let i = 1; i <= N; i++) {
make(i);
}
const queries = [[1, 2], [2, 4]];
for (let i = 0; i < Q; i++) {
const u = queries[i][0];
const v = queries[i][1];
union(u, v);
const a = Math.min(...st);
const b = Math.max(...st);
console.log(b - a);
}
}
main();
|
Time Complexity: O(Q(logN) + N), where Q is the number of queries and N is the number of nodes.
Auxiliary Space: O(N), where N is the number of nodes.
Share your thoughts in the comments
Please Login to comment...