Maximum product of a pair of nodes from largest connected component in a Graph
Last Updated :
23 Jul, 2025
Given an undirected weighted graph G consisting of N vertices and M edges, and two arrays Edges[][2] and Weight[] consisting of M edges of the graph and weights of each edge respectively, the task is to find the maximum product of any two vertices of the largest connected component of the graph, formed by connecting all edges with the same weight.
Examples:
Input: N = 4, Edges[][] = {{1, 2}, {1, 2}, {2, 3}, {2, 3}, {2, 4}}, Weight[] = {1, 2, 1, 3, 3}
Output: 12
Explanation:

- Components of edges of weight 1, 1 ? 2 ? 3. The maximum product of any two vertices of this component is 6.
- Components of edges of weight 2, 1 ? 2. The maximum product of any two vertices of this component is 2.
- Components of edges of weight 3, 4 ? 2 ? 3. The maximum product of any two vertices of this component is 12.
Therefore, the maximum product among all the connected components of size 3 (which is maximum) is 12.
Input: N = 5, Edges[][] = {{1, 5}, {2, 5}, {3, 5}, {4, 5}, {1, 2}, {2, 3}, {3, 4}}, Weight[] = {1, 1, 1, 1, 2, 2, 2}
Output: 20
Approach: The given problem can be solved by performing the DFS traversal on the given graph and maximize the product of the first and second maximum node for all the connected components of the same weight. Follow the steps below to solve the problem:
- Store all the edges corresponding to all the unique weight in a map M.
- Initialize a variable, say res as 0 to store the maximum product of any two nodes of the connected components of the same weights.
- Traverse the map and for each key as weight create a graph by connecting all the edges mapped with the particular weight and perform the following operations:
- Find the value of the maximum(say M1) and the second maximum(say M2) node's value and the size of all the connected components of the graph by performing the DFS Traversal on the created graph.
- Update the value of res to the maximum of res, M1, and M2 if the size of the currently connected components is at least the largest size connected component found previously.
- After completing the above steps, print the value of res as the maximum product.
Below is the implementation of the above approach:
C++
// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
// Stores the first and second largest
// element in a connected component
int Max, sMax;
// Stores the count of nodes
// in the connected components
int cnt = 0;
// Function to perform DFS Traversal
// on a given graph and find the first
// and the second largest elements
void dfs(int u, int N, vector<bool>& vis,
vector<vector<int> >& adj)
{
// Update the maximum value
if (u > Max) {
sMax = Max;
Max = u;
}
// Update the second max value
else if (u > sMax) {
sMax = u;
}
// Increment size of component
cnt++;
// Mark current node visited
vis[u] = true;
// Traverse the adjacent nodes
for (auto to : adj[u]) {
// If to is not already visited
if (!vis[to]) {
dfs(to, N, vis, adj);
}
}
return;
}
// Function to find the maximum
// product of a connected component
int MaximumProduct(
int N, vector<pair<int, int> > Edge,
vector<int> wt)
{
// Stores the count of edges
int M = wt.size();
// Stores all the edges mapped
// with a particular weight
unordered_map<int,
vector<pair<int, int> > >
mp;
// Update the map mp
for (int i = 0; i < M; i++)
mp[wt[i]].push_back(Edge[i]);
// Stores the result
int res = 0;
// Traverse the map mp
for (auto i : mp) {
// Stores the adjacency list
vector<vector<int> > adj(N + 1);
// Stores the edges of
// a particular weight
vector<pair<int, int> > v = i.second;
// Traverse the vector v
for (int j = 0; j < v.size(); j++) {
int U = v[j].first;
int V = v[j].second;
// Add an edge
adj[U].push_back(V);
adj[V].push_back(U);
}
// Stores if a vertex
// is visited or not
vector<bool> vis(N + 1, 0);
// Stores the maximum
// size of a component
int cntMax = 0;
// Iterate over the range [1, N]
for (int u = 1; u <= N; u++) {
// Assign Max, sMax, count = 0
Max = sMax = cnt = 0;
// If vertex u is not visited
if (!vis[u]) {
dfs(u, N, vis, adj);
// If cnt is greater
// than cntMax
if (cnt > cntMax) {
// Update the res
res = Max * sMax;
cntMax = cnt;
}
// If already largest
// connected component
else if (cnt == cntMax) {
// Update res
res = max(res, Max * sMax);
}
}
}
}
// Return res
return res;
}
// Driver Code
int main()
{
int N = 5;
vector<pair<int, int> > Edges
= { { 1, 2 }, { 2, 5 }, { 3, 5 }, { 4, 5 }, { 1, 2 }, { 2, 3 }, { 3, 4 } };
vector<int> Weight = { 1, 1, 1, 1,
2, 2, 2 };
cout << MaximumProduct(N, Edges, Weight);
return 0;
}
Java
// Java code to implement the approach
import java.util.*;
class GFG {
// Stores the first and second largest
// element in a connected component
static int Max, sMax, cnt;
// Function to perform DFS Traversal
// on a given graph and find the first
// and the second largest elements
static void dfs(int u, int N, List<Boolean> vis,
List<List<Integer> > adj) {
// Update the maximum value
if (u > Max) {
sMax = Max;
Max = u;
}
// Update the second max value
else if (u > sMax) {
sMax = u;
}
// Increment size of component
cnt++;
// Mark current node visited
vis.set(u, true);
// Traverse the adjacent nodes
for (int i = 0; i < adj.get(u).size(); i++) {
int to = adj.get(u).get(i);
// If to is not already visited
if (!vis.get(to)) {
dfs(to, N, vis, adj);
}
}
}
// Function to find the maximum
// product of a connected component
static int MaximumProduct(int N, List<int[]> Edge, List<Integer> wt) {
int M = wt.size();
// Stores all the edges mapped
// with a particular weight
Map<Integer, List<int[]> > mp = new HashMap<>();
for (int i = 0; i < M; i++) {
if (!mp.containsKey(wt.get(i))) {
mp.put(wt.get(i), new ArrayList<>());
}
mp.get(wt.get(i)).add(Edge.get(i));
}
List<Integer> keys = new ArrayList<>(mp.keySet());
Collections.sort(keys, Collections.reverseOrder());
// Stores the result
int res = 0;
// Traverse the map mp
for (Integer i : keys) {
List<List<Integer> > adj = new ArrayList<>();
for (int j = 0; j <= N; j++)
adj.add(new ArrayList<>());
// Stores the edges of
// a particular weight
List<int[]> v = mp.get(i);
// Traverse the vector v
for (int j = 0; j < v.size(); j++) {
int U = v.get(j)[0];
int V = v.get(j)[1];
adj.get(U).add(V);
adj.get(V).add(U);
}
// Stores the maximum
// size of a component
List<Boolean> vis = new ArrayList<>();
for (int j = 0; j <= N; j++)
vis.add(false);
int cntMax = 0;
for (int u = 1; u <= N; u++) {
// Assign Max, sMax, count = 0
Max = 0;
sMax = 0;
cnt = 0;
// If vertex u is not visited
if (!vis.get(u)) {
dfs(u, N, vis, adj);
// If cnt is greater
// than cntMax
if (cnt > cntMax) {
// Update the res
res = Max * sMax;
cntMax = cnt;
}
// If already largest
// connected component
else if (cnt == cntMax) {
// Update res
res = Math.max(res, Max * sMax);
}
}
}
}
return res;
}
// Driver code
public static void main(String[] args) {
int N = 5;
List<int[]> Edges = new ArrayList<>();
Edges.add(new int[]{1, 2});
Edges.add(new int[]{2, 5});
Edges.add(new int[]{3, 5});
Edges.add(new int[]{4, 5});
Edges.add(new int[]{1, 2});
Edges.add(new int[]{2, 3});
Edges.add(new int[]{3, 4});
List<Integer> Weights = Arrays.asList(1, 1, 1, 1, 2, 2, 2);
System.out.println(MaximumProduct(N, Edges, Weights));
}
}
// This code is contributed by phasing17
Python
# Function to perform DFS Traversal
# on a given graph and find the first
# and the second largest elements
def dfs(u, N, vis, adj):
global Max
global sMax
global cnt
# Update the maximum value
if u > Max:
sMax = Max
Max = u
# Update the second max value
elif u > sMax:
sMax = u
# Increment size of component
cnt+=1
# Mark current node visited
vis[u] = True
# Traverse the adjacent nodes
for to in adj[u]:
# If to is not already visited
if not vis[to]:
dfs(to, N, vis, adj)
def maximumProduct(N, Edge, wt):
# Stores the count of edges
M = len(wt)
# Stores all the edges mapped
# with a particular weight
mp = {}
# Update the map mp
for i in range(M):
weight = wt[i]
if weight not in mp:
mp[weight] = [Edge[i]]
else:
mp[weight].append(Edge[i])
# Stores the result
res = 0
keys = list(mp.keys())
keys.sort(reverse=True)
# Traverse the map mp
for key in keys:
weight = mp[key]
# Stores the adjacency list
adj = [ [] for _ in range(N + 1)]
# Stores the edges of
# a particular weight
v = weight
# Traverse the vector v
for j in range(len(v)):
U, V = v[j]
# Add an edge
adj[U].append(V)
adj[V].append(U)
# Stores if a vertex
# is visited or not
vis = [False for _ in range(N + 1)]
# Stores the maximum
# size of a component
cntMax = 0
# Iterate over the range [1, N]
for u in range(1, N+1):
global Max
global sMax
global cnt
# Assign Max, sMax, count = 0
Max = 0
sMax = 0
cnt = 0;
# If vertex u is not visited
if not vis[u]:
dfs(u, N, vis, adj);
# If cnt is greater
# than cntMax
if cnt > cntMax:
# Update the res
res = Max * sMax;
cntMax = cnt;
# If already largest
# connected component
elif cnt == cntMax:
# Update res
res = max(res, Max * sMax);
return res
# driver code
N = 5;
Edges = [[1, 2], [2, 5], [3, 5], [4, 5], [1, 2], [2, 3], [3, 4]];
Weight = [1, 1, 1, 1, 2, 2, 2];
print(maximumProduct(N, Edges, Weight));
# This code is contributed by phasing17.
C#
// C# code to implement the approach
using System;
using System.Collections.Generic;
using System.Linq;
class MainClass {
// Stores the first and second largest
// element in a connected component
static int Max, sMax;
// Stores the count of nodes
// in the connected components
static int cnt = 0;
// Function to perform DFS Traversal
// on a given graph and find the first
// and the second largest elements
static void dfs(int u, int N, List<bool> vis,
List<List<int> > adj)
{
// Update the maximum value
if (u > Max) {
sMax = Max;
Max = u;
}
// Update the second max value
else if (u > sMax) {
sMax = u;
}
// Increment size of component
cnt++;
// Mark current node visited
vis[u] = true;
// Traverse the adjacent nodes
for (int i = 0; i < adj[u].Count; i++) {
int to = adj[u][i];
// If to is not already visited
if (!vis[to]) {
dfs(to, N, vis, adj);
}
}
return;
}
// Function to find the maximum
// product of a connected component
static int MaximumProduct(int N,
List<Tuple<int, int> > Edge,
List<int> wt)
{
// Stores the count of edges
int M = wt.Count;
// Stores all the edges mapped
// with a particular weight
Dictionary<int, List<Tuple<int, int> > > mp
= new Dictionary<int,
List<Tuple<int, int> > >();
// Update the map mp
for (int i = 0; i < M; i++) {
if (!mp.ContainsKey(wt[i])) {
mp.Add(wt[i], new List<Tuple<int, int> >());
}
mp[wt[i]].Add(Edge[i]);
}
var keys = mp.Keys.ToList();
keys.Sort();
keys.Reverse();
// Stores the result
int res = 0;
// Traverse the map mp
foreach(var i in keys)
{
// Stores the adjacency list
List<List<int> > adj = new List<List<int> >();
for (int j = 0; j <= N; j++)
adj.Add(new List<int>());
// Stores the edges of
// a particular weight
List<Tuple<int, int> > v = mp[i];
// Traverse the vector v
for (int j = 0; j < v.Count; j++) {
int U = v[j].Item1;
int V = v[j].Item2;
// Add an edge
adj[U].Add(V);
adj[V].Add(U);
}
// Stores if a vertex
// is visited or not
List<bool> vis = new List<bool>();
for (int j = 0; j <= N; j++)
vis.Add(false);
// Stores the maximum
// size of a component
int cntMax = 0;
// Iterate over the range [1, N]
for (int u = 1; u <= N; u++) {
// Assign Max, sMax, count = 0
Max = 0;
sMax = 0;
cnt = 0;
// If vertex u is not visited
if (!vis[u]) {
dfs(u, N, vis, adj);
// If cnt is greater
// than cntMax
if (cnt > cntMax) {
// Update the res
res = Max * sMax;
cntMax = cnt;
}
// If already largest
// connected component
else if (cnt == cntMax) {
// Update res
res = Math.Max(res, Max * sMax);
}
}
}
}
// Return res
return res;
}
// Driver Code
public static void Main(string[] args)
{
int N = 5;
List<Tuple<int, int> > Edges
= new List<Tuple<int, int> >();
Edges.Add(Tuple.Create(1, 2));
Edges.Add(Tuple.Create(2, 5));
Edges.Add(Tuple.Create(3, 5));
Edges.Add(Tuple.Create(4, 5));
Edges.Add(Tuple.Create(1, 2));
Edges.Add(Tuple.Create(2, 3));
Edges.Add(Tuple.Create(3, 4));
List<int> Weight
= new List<int>{ 1, 1, 1, 1, 2, 2, 2 };
Console.WriteLine(MaximumProduct(N, Edges, Weight));
}
}
// This code is contributed by phasing17
JavaScript
// JavaScript implementation of the approach
function dfs(u, N, vis, adj) {
// Update the maximum value
if (u > Max) {
sMax = Max;
Max = u;
}
// Update the second max value
else if (u > sMax) {
sMax = u;
}
// Increment size of component
cnt++;
// Mark current node visited
vis[u] = true;
// Traverse the adjacent nodes
for (const to of adj[u]) {
// If to is not already visited
if (!vis[to]) {
dfs(to, N, vis, adj);
}
}
}
function maximumProduct(N, Edge, wt) {
// Stores the count of edges
const M = wt.length;
// Stores all the edges mapped
// with a particular weight
const mp = {};
// Update the map mp
for (let i = 0; i < M; i++) {
const weight = wt[i];
if (!mp.hasOwnProperty(weight)) {
mp[weight] = [Edge[i]];
} else {
mp[weight].push(Edge[i]);
}
}
// Stores the result
let res = 0;
let keys = Object.keys(mp)
keys.sort(function(a, b)
{
return -a + b;
})
// Traverse the map mp
for (const key of keys) {
let weight = mp[key]
// Stores the adjacency list
const adj = new Array(N + 1);
for (var i = 0; i <= N; i++)
adj[i] = []
// Stores the edges of
// a particular weight
const v = weight;
// Traverse the vector v
for (let j = 0; j < v.length; j++) {
const U = v[j][0];
const V = v[j][1];
// Add an edge
let l1 = adj[U]
l1.push(V)
adj[U] = l1
let l2 = adj[V]
l2.push(U)
adj[V] = l2
}
// Stores if a vertex
// is visited or not
const vis = new Array(N + 1).fill(false)
// Stores the maximum
// size of a component
let cntMax = 0;
// Iterate over the range [1, N]
for (let u = 1; u <= N; u++) {
// Assign Max, sMax, count = 0
Max = 0
sMax = 0
cnt = 0;
// If vertex u is not visited
if (!vis[u]) {
dfs(u, N, vis, adj);
// If cnt is greater
// than cntMax
if (cnt > cntMax) {
// Update the res
res = Max * sMax;
cntMax = cnt;
}
// If already largest
// connected component
else if (cnt == cntMax) {
// Update res
res = Math.max(res, Max * sMax);
}
}
}
}
return res
}
// driver code
const N = 5;
const Edges = [[1, 2], [2, 5], [3, 5], [4, 5], [1, 2], [2, 3], [3, 4]];
const Weight = [1, 1, 1, 1, 2, 2, 2];
console.log(maximumProduct(N, Edges, Weight));
Time Complexity: O(N2 * log N + M)
Auxiliary Space: O(N2)
Approach: Optimized Graph Traversal with Component Tracking
The goal is to efficiently find the maximum product of any two nodes in the largest connected component for subgraphs with identical edge weights. This can be achieved by breaking the graph down into weighted components and computing the properties of each component. We can optimize the algorithm by using Union-Find (Disjoint Set Union, DSU) to quickly determine and merge components, and then calculating the product of the largest two nodes in each component.
Steps:
- Use a dictionary to group edges by their weights ensures we are only processing edges that could form a valid component together.
- Implement Union-Find to dynamically group nodes into connected components as we iterate through the edges.
- Once the components for a particular weight are formed, determine the maximum and second maximum nodes for each component.
- The result for each component weight is the maximum of the node products across all its components.
Below is the implementation of above approach:
C++
#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;
class DSU {
private:
vector<int> parent;
vector<int> rank;
vector<int> maxNode;
public:
DSU(int size) {
parent.resize(size);
rank.resize(size, 1);
maxNode.resize(size);
for (int i = 0; i < size; ++i) {
parent[i] = i;
maxNode[i] = i;
}
}
int find(int x) {
if (parent[x] != x)
parent[x] = find(parent[x]);
return parent[x];
}
void union_set(int x, int y) {
int xr = find(x), yr = find(y);
if (xr == yr)
return;
else if (rank[xr] < rank[yr]) {
parent[xr] = yr;
maxNode[yr] = max(maxNode[xr], maxNode[yr]);
} else if (rank[xr] > rank[yr]) {
parent[yr] = xr;
maxNode[xr] = max(maxNode[xr], maxNode[yr]);
} else {
parent[yr] = xr;
rank[xr]++;
maxNode[xr] = max(maxNode[xr], maxNode[yr]);
}
}
int getMaxNode(int x) { return maxNode[x]; }
};
int maximumProduct(int N, vector<vector<int>>& Edges, vector<int>& Weight) {
unordered_map<int, vector<vector<int>>> edgeMap;
for (int i = 0; i < Edges.size(); ++i) {
int u = Edges[i][0], v = Edges[i][1];
edgeMap[Weight[i]].push_back({u, v});
}
int maxProduct = 0;
for (auto& entry : edgeMap) {
int weight = entry.first;
vector<vector<int>>& edges = entry.second;
DSU dsu(N + 1); // Using 1-based indexing
for (auto& edge : edges)
dsu.union_set(edge[0], edge[1]);
unordered_map<int, vector<int>> componentMax;
for (int i = 1; i <= N; ++i) {
int root = dsu.find(i);
componentMax[root].push_back(i);
}
for (auto& nodes : componentMax) {
if (nodes.second.size() >= 2) {
sort(nodes.second.rbegin(), nodes.second.rend());
maxProduct = max(maxProduct, nodes.second[0] * nodes.second[1]);
}
}
}
return (maxProduct > 0) ? maxProduct : -1;
}
int main() {
// Example
int N = 5;
vector<vector<int>> Edges = { { 1, 2 }, { 2, 5 }, { 3, 5 }, { 4, 5 },
{ 1, 2 }, { 2, 3 }, { 3, 4 } };
vector<int> Weight = { 1, 1, 1, 1, 2, 2, 2 };
cout << maximumProduct(N, Edges, Weight) << endl; // Output: 20
return 0;
}
Java
import java.util.*;
class DSU {
private int[] parent;
private int[] rank;
private int[] maxNode;
public DSU(int size)
{
parent = new int[size];
rank = new int[size];
maxNode = new int[size];
for (int i = 0; i < size; ++i) {
parent[i] = i;
rank[i] = 1;
maxNode[i] = i;
}
}
public int find(int x)
{
if (parent[x] != x)
parent[x] = find(parent[x]);
return parent[x];
}
public void union(int x, int y)
{
int xr = find(x), yr = find(y);
if (xr == yr)
return;
else if (rank[xr] < rank[yr]) {
parent[xr] = yr;
maxNode[yr]
= Math.max(maxNode[xr], maxNode[yr]);
}
else if (rank[xr] > rank[yr]) {
parent[yr] = xr;
maxNode[xr]
= Math.max(maxNode[xr], maxNode[yr]);
}
else {
parent[yr] = xr;
rank[xr]++;
maxNode[xr]
= Math.max(maxNode[xr], maxNode[yr]);
}
}
public int getMaxNode(int x) { return maxNode[x]; }
}
public class MaximumProduct {
public static int maximumProduct(int N, int[][] Edges,
int[] Weight)
{
Map<Integer, List<int[]> > edgeMap
= new HashMap<>();
for (int i = 0; i < Edges.length; ++i) {
int u = Edges[i][0], v = Edges[i][1];
edgeMap
.computeIfAbsent(Weight[i],
k -> new ArrayList<>())
.add(new int[] { u, v });
}
int maxProduct = 0;
for (Map.Entry<Integer, List<int[]> > entry :
edgeMap.entrySet()) {
int weight = entry.getKey();
List<int[]> edges = entry.getValue();
DSU dsu
= new DSU(N + 1); // Using 1-based indexing
for (int[] edge : edges)
dsu.union(edge[0], edge[1]);
Map<Integer, List<Integer> > componentMax
= new HashMap<>();
for (int i = 1; i <= N; ++i) {
int root = dsu.find(i);
componentMax
.computeIfAbsent(root,
k -> new ArrayList<>())
.add(i);
}
for (List<Integer> nodes :
componentMax.values()) {
if (nodes.size() >= 2) {
Collections.sort(
nodes, Collections.reverseOrder());
maxProduct = Math.max(
maxProduct,
nodes.get(0) * nodes.get(1));
}
}
}
return (maxProduct > 0) ? maxProduct : -1;
}
public static void main(String[] args)
{
// Example
int N = 5;
int[][] Edges
= { { 1, 2 }, { 2, 5 }, { 3, 5 }, { 4, 5 },
{ 1, 2 }, { 2, 3 }, { 3, 4 } };
int[] Weight = { 1, 1, 1, 1, 2, 2, 2 };
System.out.println(
maximumProduct(N, Edges, Weight)); // Output: 20
}
}
// This code is contributed by Shivam Gupta
Python
class DSU:
def __init__(self, size):
self.parent = list(range(size))
self.rank = [1] * size
self.max_node = list(range(size)) # Track max node in component
def find(self, x):
if self.parent[x] != x:
self.parent[x] = self.find(self.parent[x])
return self.parent[x]
def union(self, x, y):
xr, yr = self.find(x), self.find(y)
if xr == yr:
return
elif self.rank[xr] < self.rank[yr]:
self.parent[xr] = yr
self.max_node[yr] = max(self.max_node[xr], self.max_node[yr])
elif self.rank[xr] > self.rank[yr]:
self.parent[yr] = xr
self.max_node[xr] = max(self.max_node[xr], self.max_node[yr])
else:
self.parent[yr] = xr
self.rank[xr] += 1
self.max_node[xr] = max(self.max_node[xr], self.max_node[yr])
def maximumProduct(N, Edges, Weight):
from collections import defaultdict
edge_map = defaultdict(list)
for i, (u, v) in enumerate(Edges):
edge_map[Weight[i]].append((u, v))
max_product = 0
for weight, edges in edge_map.items():
dsu = DSU(N + 1) # Using 1-based indexing
for u, v in edges:
dsu.union(u, v)
# Find the two largest distinct nodes in each component
component_max = defaultdict(list)
for i in range(1, N + 1):
root = dsu.find(i)
component_max[root].append(i)
for nodes in component_max.values():
if len(nodes) >= 2:
sorted_nodes = sorted(nodes, reverse=True)
max_product = max(
max_product, sorted_nodes[0] * sorted_nodes[1])
return max_product if max_product > 0 else -1
# Example
N = 5
Edges = [(1, 2), (2, 5), (3, 5), (4, 5), (1, 2), (2, 3), (3, 4)]
Weight = [1, 1, 1, 1, 2, 2, 2]
print(maximumProduct(N, Edges, Weight)) # Output: 20
JavaScript
class DSU {
constructor(size) {
this.parent = new Array(size).fill().map((_, i) => i);
this.rank = new Array(size).fill(1);
this.maxNode = [...Array(size).keys()];
}
find(x) {
if (this.parent[x] !== x)
this.parent[x] = this.find(this.parent[x]);
return this.parent[x];
}
union(x, y) {
let xr = this.find(x), yr = this.find(y);
if (xr === yr)
return;
else if (this.rank[xr] < this.rank[yr]) {
this.parent[xr] = yr;
this.maxNode[yr] = Math.max(this.maxNode[xr], this.maxNode[yr]);
}
else if (this.rank[xr] > this.rank[yr]) {
this.parent[yr] = xr;
this.maxNode[xr] = Math.max(this.maxNode[xr], this.maxNode[yr]);
}
else {
this.parent[yr] = xr;
this.rank[xr]++;
this.maxNode[xr] = Math.max(this.maxNode[xr], this.maxNode[yr]);
}
}
getMaxNode(x) { return this.maxNode[x]; }
}
function maximumProduct(N, Edges, Weight) {
const edgeMap = new Map();
for (let i = 0; i < Edges.length; ++i) {
const [u, v] = Edges[i];
const weight = Weight[i];
if (!edgeMap.has(weight))
edgeMap.set(weight, []);
edgeMap.get(weight).push([u, v]);
}
let maxProduct = 0;
for (const [weight, edges] of edgeMap.entries()) {
const dsu = new DSU(N + 1); // Using 1-based indexing
for (const [u, v] of edges)
dsu.union(u, v);
const componentMax = new Map();
for (let i = 1; i <= N; ++i) {
const root = dsu.find(i);
if (!componentMax.has(root))
componentMax.set(root, []);
componentMax.get(root).push(i);
}
for (const nodes of componentMax.values()) {
if (nodes.length >= 2) {
nodes.sort((a, b) => b - a);
maxProduct = Math.max(maxProduct, nodes[0] * nodes[1]);
}
}
}
return (maxProduct > 0) ? maxProduct : -1;
}
// Example
const N = 5;
const Edges = [[1, 2], [2, 5], [3, 5], [4, 5], [1, 2], [2, 3], [3, 4]];
const Weight = [1, 1, 1, 1, 2, 2, 2];
console.log(maximumProduct(N, Edges, Weight)); // Output: 20
Time Complexity: O(M*N), where M is the number of edges and N is the number of nodes. The log factor is due to the union-find operations.
Auxilary Space: O(N), primarily for the DSU data structures.
Similar Reads
Basics & Prerequisites
Data Structures
Array Data StructureIn this article, we introduce array, implementation in different popular languages, its basic operations and commonly seen problems / interview questions. An array stores items (in case of C/C++ and Java Primitive Arrays) or their references (in case of Python, JS, Java Non-Primitive) at contiguous
3 min read
String in Data StructureA string is a sequence of characters. The following facts make string an interesting data structure.Small set of elements. Unlike normal array, strings typically have smaller set of items. For example, lowercase English alphabet has only 26 characters. ASCII has only 256 characters.Strings are immut
2 min read
Hashing in Data StructureHashing is a technique used in data structures that efficiently stores and retrieves data in a way that allows for quick access. Hashing involves mapping data to a specific index in a hash table (an array of items) using a hash function. It enables fast retrieval of information based on its key. The
2 min read
Linked List Data StructureA linked list is a fundamental data structure in computer science. It mainly allows efficient insertion and deletion operations compared to arrays. Like arrays, it is also used to implement other data structures like stack, queue and deque. Hereâs the comparison of Linked List vs Arrays Linked List:
2 min read
Stack Data StructureA Stack is a linear data structure that follows a particular order in which the operations are performed. The order may be LIFO(Last In First Out) or FILO(First In Last Out). LIFO implies that the element that is inserted last, comes out first and FILO implies that the element that is inserted first
2 min read
Queue Data StructureA Queue Data Structure is a fundamental concept in computer science used for storing and managing data in a specific order. It follows the principle of "First in, First out" (FIFO), where the first element added to the queue is the first one to be removed. It is used as a buffer in computer systems
2 min read
Tree Data StructureTree Data Structure is a non-linear data structure in which a collection of elements known as nodes are connected to each other via edges such that there exists exactly one path between any two nodes. Types of TreeBinary Tree : Every node has at most two childrenTernary Tree : Every node has at most
4 min read
Graph Data StructureGraph Data Structure is a collection of nodes connected by edges. It's used to represent relationships between different entities. If you are looking for topic-wise list of problems on different topics like DFS, BFS, Topological Sort, Shortest Path, etc., please refer to Graph Algorithms. Basics of
3 min read
Trie Data StructureThe Trie data structure is a tree-like structure used for storing a dynamic set of strings. It allows for efficient retrieval and storage of keys, making it highly effective in handling large datasets. Trie supports operations such as insertion, search, deletion of keys, and prefix searches. In this
15+ min read
Algorithms
Searching AlgorithmsSearching algorithms are essential tools in computer science used to locate specific items within a collection of data. In this tutorial, we are mainly going to focus upon searching in an array. When we search an item in an array, there are two most common algorithms used based on the type of input
2 min read
Sorting AlgorithmsA Sorting Algorithm is used to rearrange a given array or list of elements in an order. For example, a given array [10, 20, 5, 2] becomes [2, 5, 10, 20] after sorting in increasing order and becomes [20, 10, 5, 2] after sorting in decreasing order. There exist different sorting algorithms for differ
3 min read
Introduction to RecursionThe process in which a function calls itself directly or indirectly is called recursion and the corresponding function is called a recursive function. A recursive algorithm takes one step toward solution and then recursively call itself to further move. The algorithm stops once we reach the solution
14 min read
Greedy AlgorithmsGreedy algorithms are a class of algorithms that make locally optimal choices at each step with the hope of finding a global optimum solution. At every step of the algorithm, we make a choice that looks the best at the moment. To make the choice, we sometimes sort the array so that we can always get
3 min read
Graph AlgorithmsGraph is a non-linear data structure like tree data structure. The limitation of tree is, it can only represent hierarchical data. For situations where nodes or vertices are randomly connected with each other other, we use Graph. Example situations where we use graph data structure are, a social net
3 min read
Dynamic Programming or DPDynamic Programming is an algorithmic technique with the following properties.It is mainly an optimization over plain recursion. Wherever we see a recursive solution that has repeated calls for the same inputs, we can optimize it using Dynamic Programming. The idea is to simply store the results of
3 min read
Bitwise AlgorithmsBitwise algorithms in Data Structures and Algorithms (DSA) involve manipulating individual bits of binary representations of numbers to perform operations efficiently. These algorithms utilize bitwise operators like AND, OR, XOR, NOT, Left Shift, and Right Shift.BasicsIntroduction to Bitwise Algorit
4 min read
Advanced
Segment TreeSegment Tree is a data structure that allows efficient querying and updating of intervals or segments of an array. It is particularly useful for problems involving range queries, such as finding the sum, minimum, maximum, or any other operation over a specific range of elements in an array. The tree
3 min read
Pattern SearchingPattern searching algorithms are essential tools in computer science and data processing. These algorithms are designed to efficiently find a particular pattern within a larger set of data. Patten SearchingImportant Pattern Searching Algorithms:Naive String Matching : A Simple Algorithm that works i
2 min read
GeometryGeometry is a branch of mathematics that studies the properties, measurements, and relationships of points, lines, angles, surfaces, and solids. From basic lines and angles to complex structures, it helps us understand the world around us.Geometry for Students and BeginnersThis section covers key br
2 min read
Interview Preparation
Practice Problem