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++
// Below is the C++ code for above approach
#include <bits/stdc++.h>
#define ll long long
using namespace std;
// parent array to store the parent of each
// component of the graph
ll parent[100010];
// Array used to apply DSU by size in order
// to fasten the DSU functions
ll sizez[100010];
// Frequency array to optimize the find the
// frequency of size of components in the graph
ll freq[100010];
// set to store different sizes of the component
set<ll> st;
// This function is used to initialize our DSU
// data structure
void make(ll i)
{
parent[i] = i;
sizez[i] = 1;
freq[1]++;
}
// This function is used to find the parent of
// each component of the graph
ll find(ll v)
{
if (v == parent[v])
return v;
// Path compression
// technique of DSU
return parent[v] = find(parent[v]);
}
// This function is used to Merge two components
// together it also updates our frequency array
// and set with new sizes and removes older sizes
void Union(ll a, ll b)
{
a = find(a);
b = find(b);
if (a != b) {
if (sizez[a] < sizez[b])
swap(a, b);
// Decreasing the frequency of older size
freq[sizez[a]]--;
// Removing the older size if frequency
// reaches to 0
if (freq[sizez[a]] == 0)
st.erase(st.find(sizez[a]));
// Decreasing the frequency of older size
freq[sizez[b]]--;
// Removing the older size if frequency
// reaches to 0
if (freq[sizez[b]] == 0)
st.erase(st.find(sizez[b]));
parent[b] = a;
sizez[a] += sizez[b];
// Incrementing the frequency of new size
freq[sizez[a]]++;
// Inserting the new size in the set
if (freq[sizez[a]] == 1)
st.insert(sizez[a]);
}
}
// Driver Function
int main()
{
ll N, Q;
N = 4;
Q = 2;
vector<vector<int> > queries = { { 1, 2 }, { 2, 4 } };
// Initial component size is 1
st.insert(1);
// Initialize our DSU
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;
// Finding the minimum difference between
// adjacent element of sorted set
for (auto e : st) {
// If any element has frequency greater
// than 1, answer will be 0
if (freq[e] > 1) {
ans = 0;
break;
}
ans = min(ans, e - pre);
pre = e;
}
if (ans == INT_MAX)
ans = 0;
cout << ans << endl;
}
}
Java
// Below is the Java code for above approach
import java.util.*;
public class Main {
// parent array to store the parent of each
// component of the graph
static int[] parent;
// Array used to apply DSU by size in order
// to fasten the DSU functions
static int[] sizez;
// Frequency array to optimize the find the
// frequency of size of components in the graph
static int[] freq;
// set to store different sizes of the component
static TreeSet<Integer> st;
// This function is used to initialize our DSU
// data structure
static void make(int i) {
parent[i] = i;
sizez[i] = 1;
freq[1]++;
}
// This function is used to find the parent of
// each component of the graph
static int find(int v) {
if (v == parent[v])
return v;
// Path compression
// technique of DSU
return parent[v] = find(parent[v]);
}
// This function is used to Merge two components
// together it also updates our frequency array
// and set with new sizes and removes older sizes
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;
}
// Decreasing the frequency of older size
freq[sizez[a]]--;
if (freq[sizez[a]] == 0)
st.remove(sizez[a]);
// Removing the older size if frequency
// reaches to 0
freq[sizez[b]]--;
if (freq[sizez[b]] == 0)
st.remove(sizez[b]);
parent[b] = a;
sizez[a] += sizez[b];
// Incrementing the frequency of new size
freq[sizez[a]]++;
// Inserting the new size in the set
if (freq[sizez[a]] == 1)
st.add(sizez[a]);
}
}
// Driver code
public static void main(String[] args) {
// input
int N = 4;
int Q = 2;
int[][] queries = { { 1, 2 }, { 2, 4 } };
// Initial component size is 1
st = new TreeSet<>();
st.add(1);
parent = new int[N + 1];
sizez = new int[N + 1];
freq = new int[N + 1];
// Initialize our DSU
for (int i = 1; i <= N; i++) {
make(i);
}
// Finding the minimum difference between
// adjacent element of sorted set
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 any element has frequency greater
// than 1, answer will be 0
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
# Below is the Python code for above approach
# Initialize parent array to store the parent of each
# component of the graph
parent = [0] * 100010
# Array used to apply DSU by size in order
# to fasten the DSU functions
sizez = [0] * 100010
# Frequency array to optimize finding the
# frequency of component sizes in the graph
freq = [0] * 100010
# Set to store different sizes of the components
st = set()
# This function initializes the DSU
# data structure
def make(i):
parent[i] = i
sizez[i] = 1
freq[1] += 1
# This function finds the parent of each
# component in the graph using path compression
def find(v):
if v == parent[v]:
return v
parent[v] = find(parent[v])
return parent[v]
# This function is used to Merge two components
# together it also updates our frequency array
# and set with new sizes and removes older sizes
def Union(a, b):
a = find(a)
b = find(b)
if a != b:
if sizez[a] < sizez[b]:
a, b = b, a
# Decrease the frequency of older size
freq[sizez[a]] -= 1
# Remove the older size if frequency reaches 0
if freq[sizez[a]] == 0:
st.remove(sizez[a])
# Decrease the frequency of older size
freq[sizez[b]] -= 1
# Remove the older size if frequency reaches 0
if freq[sizez[b]] == 0:
st.remove(sizez[b])
parent[b] = a
sizez[a] += sizez[b]
# Increment the frequency of new size
freq[sizez[a]] += 1
# Insert the new size into the set
if freq[sizez[a]] == 1:
st.add(sizez[a])
# Driver Code
N, Q = 4, 2
queries = [[1, 2], [2, 4]]
# Initial component size is 1
st.add(1)
# Initialize our DSU
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')
# Finding the minimum difference between
# adjacent elements of the sorted set
for e in sorted(st):
# If any element has frequency greater
# than 1, the answer will be 0
if freq[e] > 1:
ans = 0
break
ans = min(ans, e - pre)
pre = e
if ans == float('inf'):
ans = 0
print(ans)
# This code is contributed by Prasad
C#
using System;
using System.Collections.Generic;
class MainClass
{
// parent array to store the parent of each
// component of the graph
static long[] parent = new long[100010];
// Array used to apply DSU by size in order
// to fasten the DSU functions
static long[] sizez = new long[100010];
// Frequency array to optimize the find the
// frequency of size of components in the graph
static long[] freq = new long[100010];
// set to store different sizes of the component
static SortedSet<long> st = new SortedSet<long>();
// This function is used to initialize our DSU
// data structure
static void make(long i)
{
parent[i] = i;
sizez[i] = 1;
freq[1]++;
}
// This function is used to find the parent of
// each component of the graph
static long find(long v)
{
if (v == parent[v])
return v;
// Path compression
// technique of DSU
return parent[v] = find(parent[v]);
}
// This function is used to Merge two components
// together it also updates our frequency array
// and set with new sizes and removes older sizes
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);
// Decreasing the frequency of older size
freq[sizez[a]]--;
// Removing the older size if frequency
// reaches to 0
if (freq[sizez[a]] == 0)
st.Remove(sizez[a]);
// Decreasing the frequency of older size
freq[sizez[b]]--;
// Removing the older size if frequency
// reaches to 0
if (freq[sizez[b]] == 0)
st.Remove(sizez[b]);
parent[b] = a;
sizez[a] += sizez[b];
// Incrementing the frequency of new size
freq[sizez[a]]++;
// Inserting the new size in the set
if (freq[sizez[a]] == 1)
st.Add(sizez[a]);
}
}
// Driver Function
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 } };
// Initial component size is 1
st.Add(1);
// Initialize our DSU
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;
// Finding the minimum difference between
// adjacent element of sorted set
foreach (var e in st)
{
// If any element has frequency greater
// than 1, answer will be 0
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
// Initialize parent array to store the parent of eachÂ
// component of the graph
const parent = [];
for (let i = 0; i < 100010; i++) {
parent[i] = i;
}
// Array used to apply DSU by size in order
// to fasten the DSU functions
const sizez = [];
for (let i = 0; i < 100010; i++) {
sizez[i] = 1;
}
// Frequency array to optimize finding theÂ
// frequency of component sizes in the graph
const freq = [];
for (let i = 0; i < 100010; i++) {
freq[i] = 0;
}
// Set to store different sizes of the components
const st = new Set();
// This function initializes the DSUÂ
// data structure
function make(i) {
parent[i] = i;
sizez[i] = 1;
freq[1] += 1;
}
// This function finds the parent of eachÂ
// component in the graph using path compression
function find(v) {
if (v === parent[v]) {
return v;
}
parent[v] = find(parent[v]);
return parent[v];
}
// This function is used to Merge two components
// together it also updates our frequency array
// and set with new sizes and removes older sizes
function Union(a, b) {
a = find(a);
b = find(b);
if (a !== b) {
if (sizez[a] < sizez[b]) {
a = b;
}
// Decrease the frequency of older size
freq[sizez[a]] -= 1;
// Remove the older size if frequency reaches 0
if (freq[sizez[a]] === 0) {
st.delete(sizez[a]);
}
// Decrease the frequency of older size
freq[sizez[b]] -= 1;
// Remove the older size if frequency reaches 0
if (freq[sizez[b]] === 0) {
st.delete(sizez[b]);
}
parent[b] = a;
sizez[a] += sizez[b];
// Increment the frequency of new size
freq[sizez[a]] += 1;
// Insert the new size into the set
if (freq[sizez[a]] === 1) {
st.add(sizez[a]);
}
}
}
// Driver Code
const N = 4;
const Q = 2;
const queries = [[1, 2], [2, 4]];
// Initial component size is 1
st.add(1);
// Initialize our DSU
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;
// Finding the minimum difference betweenÂ
// adjacent elements of the sorted set
for (const e of st.values()) {
// If any element has frequency greaterÂ
// than 1, the answer will be 0
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)
Similar Reads
Difference between Smallest and Largest Component of the graph after each Query.
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
10 min read
Find Maximum Shortest Distance in Each Component of a Graph
Given an adjacency matrix graph[][] of a weighted graph consisting of N nodes and positive weights, the task for each connected component of the graph is to find the maximum among all possible shortest distances between every pair of nodes. Examples: Input: Output: 8 0 11 Explanation: There are thre
15+ min read
Find dependencies of each Vertex in a Directed Graph
Given a directed graph containing N vertices and M edges, the task is to find all the dependencies of each vertex in the graph and the vertex with the minimum dependency. A directed graph (or digraph) is a set of nodes connected by edges, where the edges have a direction associated with them. For e
13 min read
Pair with minimum absolute difference after solving each query
Given Q queries and an empty list. The queries can be of two types: addToList(x) : Add x to your list.removeFromList(x) : Remove x from your list.The task is, after each query, you have to print the minimum value of abs(list[i]-list[j]) where, 0<=i<=n, 0<=j<=n and i ? j and n is the tota
14 min read
Sum of the minimum elements in all connected components of an undirected graph
Given an array A of N numbers where A i represent the value of the (i+1) th node. Also given are M pair of edges where u and v represent the nodes that are connected by an edge. The task is to find the sum of the minimum element in all the connected components of the given undirected graph. If a nod
7 min read
Minimum Cost of Simple Path between two nodes in a Directed and Weighted Graph
Given a directed graph, which may contain cycles, where every edge has weight, the task is to find the minimum cost of any simple path from a given source vertex âsâ to a given destination vertex âtâ. Simple Path is the path from one vertex to another such that no vertex is visited more than once. I
10 min read
Count of connected components in given graph after removal of given Q vertices
Given an undirected graph g, the task is to find the number of coalitions formed in it after the removal of Q vertices and maximum vertices among all these connected components. A coalition is defined as the number of connected components left after removal of Q vertices i.e vertices being removed f
10 min read
Minimum number of edges between two vertices of a Graph
You are given an undirected graph G(V, E) with N vertices and M edges. We need to find the minimum number of edges between a given pair of vertices (u, v). Examples: Input: For given graph G. Find minimum number of edges between (1, 5). Output: 2Explanation: (1, 2) and (2, 5) are the only edges resu
8 min read
Minimum time taken by each job to be completed given by a Directed Acyclic Graph
Given a Directed Acyclic Graph having V vertices and E edges, where each edge {U, V} represents the Jobs U and V such that Job V can only be started only after completion of Job U. The task is to determine the minimum time taken by each job to be completed where each Job takes unit time to get compl
12 min read
Connected Components in an Undirected Graph
Given an undirected graph, the task is to return all the connected components in any order. Examples:Input: Consider the following graphExample of an undirected graphOutput: [[0, 1, 2], [3, 4]]Explanation: There are 2 different connected components.They are {0, 1, 2} and {3, 4}.Table of ContentAppro
15+ min read