Minimum difference between components of the Graph after each query
Last Updated :
17 Oct, 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 which denotes that you have to add an edge between node u and v. After each query you have to print the minimum difference possible between the size any two components of the graph. If there is only one component simply print 0.
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, simply print 0.
Input: N = 4, Q = 2, queries = [[1 2], [2 4]]
Output: [0, 2]
Explanation:
- Initial components = {{1}, {2}, {3}, {4}}
- After query[0]:
- we have components={{1 2}, {3}, {4}}
- So minimum difference = size of {3} – size of {4} = 1-1 = 0.
- After query[1]:
- We have components={{1 2 4},{3}}
- So minimum difference = size of {1 2 4} – size of {3} = 3 – 1 = 2.
Efficient Approach: We can use Disjoint-Set_Union(DSU) and Set data structure to solve this question optimally as discussed below.
For each query of creating an edge between node ‘u’ and ‘v’ , we can use Union operation of DSU to merge both the nodes into a same component. Also we can use a set to remove older sizes of the component and insert new sizes efficiently . This set will provide a sorted information about the sizes of each component existing in the graph.
Answer for each query can be obtained by 2 cases.
Case 1: If any element of the set has a frequency > 1
- Simply print 0, as we have 2 component of same size.
Case 2: If all the element in the set has frequency<=1
- Print the minimum among all the differences between adjacent elements in the sorted-set while iterating.
Follow the below steps to solve the problem:
- Create a set ‘st‘ and frequency array ‘freq‘ to store the information about the sizes of the component existing in the graph
- For each query merge the nodes ‘u‘ and ‘v‘ using the Union operation of DSU.
- Update the ‘st’ and ‘freq’, by deleting the older component sizes and inserting the new component sizes.
- Iterate the elements of the set and find the answer ‘ans‘ by the following comparison:
- If freq[element]>1 : ans=0 , break out of the iteration
- Else ans = minimum of all the differences between the consecutive elements of set iteration.
Below is the implementation of the above algorithm:
C++
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll parent[100010];
ll sizez[100010];
ll freq[100010];
set<ll> st;
void make(ll i)
{
parent[i] = i;
sizez[i] = 1;
freq[1]++;
}
ll find(ll v)
{
if (v == parent[v])
return v;
return parent[v] = find(parent[v]);
}
void Union(ll a, ll b)
{
a = find(a);
b = find(b);
if (a != b) {
if (sizez[a] < sizez[b])
swap(a, b);
freq[sizez[a]]--;
if (freq[sizez[a]] == 0)
st.erase(st.find(sizez[a]));
freq[sizez[b]]--;
if (freq[sizez[b]] == 0)
st.erase(st.find(sizez[b]));
parent[b] = a;
sizez[a] += sizez[b];
freq[sizez[a]]++;
if (freq[sizez[a]] == 1)
st.insert(sizez[a]);
}
}
int main()
{
ll N, Q;
N = 4;
Q = 2;
vector<vector< int > > queries = { { 1, 2 }, { 2, 4 } };
st.insert(1);
for ( int i = 1; i <= N; i++) {
make(i);
}
for ( int i = 0; i < Q; i++) {
ll u = queries[i][0];
ll v = queries[i][1];
Union(u, v);
ll ans = INT_MAX;
ll pre = INT_MIN;
for ( auto e : st) {
if (freq[e] > 1) {
ans = 0;
break ;
}
ans = min(ans, e - pre);
pre = e;
}
if (ans == INT_MAX)
ans = 0;
cout << ans << endl;
}
}
|
Java
import java.util.*;
public class Main {
static int [] parent;
static int [] sizez;
static int [] freq;
static TreeSet<Integer> st;
static void make( int i) {
parent[i] = i;
sizez[i] = 1 ;
freq[ 1 ]++;
}
static int find( int v) {
if (v == parent[v])
return v;
return parent[v] = find(parent[v]);
}
static void Union( int a, int b) {
a = find(a);
b = find(b);
if (a != b) {
if (sizez[a] < sizez[b]) {
int temp = a;
a = b;
b = temp;
}
freq[sizez[a]]--;
if (freq[sizez[a]] == 0 )
st.remove(sizez[a]);
freq[sizez[b]]--;
if (freq[sizez[b]] == 0 )
st.remove(sizez[b]);
parent[b] = a;
sizez[a] += sizez[b];
freq[sizez[a]]++;
if (freq[sizez[a]] == 1 )
st.add(sizez[a]);
}
}
public static void main(String[] args) {
int N = 4 ;
int Q = 2 ;
int [][] queries = { { 1 , 2 }, { 2 , 4 } };
st = new TreeSet<>();
st.add( 1 );
parent = new int [N + 1 ];
sizez = new int [N + 1 ];
freq = new int [N + 1 ];
for ( int i = 1 ; i <= N; i++) {
make(i);
}
for ( int i = 0 ; i < Q; i++) {
int u = queries[i][ 0 ];
int v = queries[i][ 1 ];
Union(u, v);
int ans = Integer.MAX_VALUE;
int pre = Integer.MIN_VALUE;
for ( int e : st) {
if (freq[e] > 1 ) {
ans = 0 ;
break ;
}
if (pre != Integer.MIN_VALUE) {
ans = Math.min(ans, e - pre);
}
pre = e;
}
System.out.println(ans);
}
}
}
|
Python3
parent = [ 0 ] * 100010
sizez = [ 0 ] * 100010
freq = [ 0 ] * 100010
st = set ()
def make(i):
parent[i] = i
sizez[i] = 1
freq[ 1 ] + = 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 sizez[a] < sizez[b]:
a, b = b, a
freq[sizez[a]] - = 1
if freq[sizez[a]] = = 0 :
st.remove(sizez[a])
freq[sizez[b]] - = 1
if freq[sizez[b]] = = 0 :
st.remove(sizez[b])
parent[b] = a
sizez[a] + = sizez[b]
freq[sizez[a]] + = 1
if freq[sizez[a]] = = 1 :
st.add(sizez[a])
N, Q = 4 , 2
queries = [[ 1 , 2 ], [ 2 , 4 ]]
st.add( 1 )
for i in range ( 1 , N + 1 ):
make(i)
for i in range (Q):
u, v = queries[i]
Union(u, v)
ans = float ( 'inf' )
pre = float ( '-inf' )
for e in sorted (st):
if freq[e] > 1 :
ans = 0
break
ans = min (ans, e - pre)
pre = e
if ans = = float ( 'inf' ):
ans = 0
print (ans)
|
C#
using System;
using System.Collections.Generic;
class MainClass
{
static long [] parent = new long [100010];
static long [] sizez = new long [100010];
static long [] freq = new long [100010];
static SortedSet< long > st = new SortedSet< long >();
static void make( long i)
{
parent[i] = i;
sizez[i] = 1;
freq[1]++;
}
static long find( long v)
{
if (v == parent[v])
return v;
return parent[v] = find(parent[v]);
}
static void Union( long a, long b)
{
a = find(a);
b = find(b);
if (a != b)
{
if (sizez[a] < sizez[b])
(a, b) = (b, a);
freq[sizez[a]]--;
if (freq[sizez[a]] == 0)
st.Remove(sizez[a]);
freq[sizez[b]]--;
if (freq[sizez[b]] == 0)
st.Remove(sizez[b]);
parent[b] = a;
sizez[a] += sizez[b];
freq[sizez[a]]++;
if (freq[sizez[a]] == 1)
st.Add(sizez[a]);
}
}
public static void Main( string [] args)
{
long N, Q;
N = 4;
Q = 2;
List<List< long >> queries = new List<List< long >> { new List< long > { 1, 2 }, new List< long > { 2, 4 } };
st.Add(1);
for ( int i = 1; i <= N; i++)
{
make(i);
}
for ( int i = 0; i < Q; i++)
{
long u = queries[i][0];
long v = queries[i][1];
Union(u, v);
long ans = int .MaxValue;
long pre = int .MinValue;
foreach ( var e in st)
{
if (freq[e] > 1)
{
ans = 0;
break ;
}
ans = Math.Min(ans, e - pre);
pre = e;
}
if (ans == int .MaxValue)
ans = 0;
Console.WriteLine(ans);
}
}
}
|
Javascript
const parent = [];
for (let i = 0; i < 100010; i++) {
parent[i] = i;
}
const sizez = [];
for (let i = 0; i < 100010; i++) {
sizez[i] = 1;
}
const freq = [];
for (let i = 0; i < 100010; i++) {
freq[i] = 0;
}
const st = new Set();
function make(i) {
parent[i] = i;
sizez[i] = 1;
freq[1] += 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 (sizez[a] < sizez[b]) {
a = b;
}
freq[sizez[a]] -= 1;
if (freq[sizez[a]] === 0) {
st. delete (sizez[a]);
}
freq[sizez[b]] -= 1;
if (freq[sizez[b]] === 0) {
st. delete (sizez[b]);
}
parent[b] = a;
sizez[a] += sizez[b];
freq[sizez[a]] += 1;
if (freq[sizez[a]] === 1) {
st.add(sizez[a]);
}
}
}
const N = 4;
const Q = 2;
const queries = [[1, 2], [2, 4]];
st.add(1);
for (let i = 1; i <= N; i++) {
make(i);
}
for (let i = 0; i < Q; i++) {
const [u, v] = queries[i];
Union(u, v);
let ans = Infinity;
let pre = -Infinity;
for (const e of st.values()) {
if (freq[e] > 1) {
ans = 0;
break ;
}
ans = Math.min(ans, e - pre);
pre = e;
}
if (ans === Infinity) {
ans = 0;
}
console.log(ans);
}
|
Time Complexity: O(Q * Sqrt(N)), where Q is the number of queries and N is the total number of nodes.
Auxiliary Space: O(N)
Share your thoughts in the comments
Please Login to comment...