Open In App

Largest component size in a graph formed by connecting non-co-prime nodes

Given a graph with N nodes and their values defined in array A, the task is to find the largest component size in a graph by connecting non-co-prime nodes. An edge is between two nodes U and V if they are non-co-prime, which means that the greatest common divisor of A[U] and A[V] should be greater than 1.

Examples:  



Input : A = [4, 6, 15, 35]
Output : 4
Graph will be :
         4
         |
         6
         |
         15
         |
         35

Input : A = [2, 3, 6, 7, 4, 12, 21, 39]
Output : 8

Naive Approach: 
We can iterate over all the pairs of nodes and check whether they are co-prime or not. If they are not co-prime, we will connect them. Once the graph is created, we will apply Depth First Search to find the maximum component size.

Below is the implementation of the above approach:  






#include <bits/stdc++.h>
using namespace std;
  
int dfs(int u, vector<int>* adj, int vis[])
{
    // mark this node as visited
    vis[u] = 1;
    int componentSize = 1;
  
    // apply dfs and add nodes belonging to this component
    for (auto it : adj[u]) {
        if (!vis[it]) {
            componentSize += dfs(it, adj, vis);
        }
    }
    return componentSize;
}
  
int maximumComponentSize(int a[], int n)
{
    // create graph and store in adjacency list form
    vector<int> adj[n];
  
    // iterate over all pair of nodes
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            // if not co-prime
            if (__gcd(a[i], a[j]) > 1)
                // build undirected graph
                adj[i].push_back(j);
            adj[j].push_back(i);
        }
    }
    int answer = 0;
  
    // visited array for dfs
    int vis[n];
    for(int k=0;k<n;k++){
      vis[k]=0;
    }
    for (int i = 0; i < n; i++) {
        if (!vis[i]) {
            answer = max(answer, dfs(i, adj, vis));
        }
    }
    return answer;
}
  
// Driver Code
int main()
{
    int n = 8;
    int A[] = { 2, 3, 6, 7, 4, 12, 21, 39 };
    cout << maximumComponentSize(A, n);
    return 0;
}




import java.util.*;
 
class GFG{
 
static int dfs(int u, Vector<Integer> []adj,
               int vis[])
{
     
    // Mark this node as visited
    vis[u] = 1;
    int componentSize = 1;
 
    // Apply dfs and add nodes belonging
    // to this component
    for(int it : adj[u])
    {
        if (vis[it] == 0)
        {
            componentSize += dfs(it, adj, vis);
        }
    }
    return componentSize;
}
 
static int maximumComponentSize(int a[], int n)
{
     
    // Create graph and store in adjacency
    // list form
    @SuppressWarnings("unchecked")
    Vector<Integer> []adj = new Vector[n];
    for(int i = 0; i < adj.length; i++)
        adj[i] = new Vector<Integer>();
         
    // Iterate over all pair of nodes
    for(int i = 0; i < n; i++)
    {
        for(int j = i + 1; j < n; j++)
        {
             
            // If not co-prime
            if (__gcd(a[i], a[j]) > 1)
             
                // Build undirected graph
                adj[i].add(j);
                 
            adj[j].add(i);
        }
    }
    int answer = 0;
 
    // Visited array for dfs
    int []vis = new int[n];
    for(int k = 0; k < n; k++)
    {
        vis[k] = 0;
    }
     
    for(int i = 0; i < n; i++)
    {
        if (vis[i] == 0)
        {
            answer = Math.max(answer,
                              dfs(i, adj, vis));
        }
    }
    return answer;
}
 
static int __gcd(int a, int b)
    return b == 0 ? a : __gcd(b, a % b);    
}
 
// Driver Code
public static void main(String[] args)
{
    int n = 8;
    int A[] = { 2, 3, 6, 7, 4, 12, 21, 39 };
     
    System.out.print(maximumComponentSize(A, n));
}
}
 
// This code is contributed by Amit Katiyar




from math import gcd
def dfs(u, adj, vis):
 
    # mark this node as visited
    vis[u] = 1
    componentSize = 1
 
    # apply dfs and add nodes belonging to this component
    for x in adj[u]:
        if (vis[x] == 0):
            componentSize += dfs(x, adj, vis)
    return componentSize
 
def maximumComponentSize(a,n):
 
    # create graph and store in adjacency list form
    adj = [[] for i in range(n)]
 
    # iterate over all pair of nodes
    for i in range(n):
        for j in range(i + 1, n):
            # if not co-prime
            if (gcd(a[i], a[j]) > 1):
                # build undirected graph
                adj[i].append(j)
            adj[j].append(i)
    answer = 0
 
    # visited array for dfs
    vis = [0 for i in range(n)]
    for i in range(n):
        if (vis[i]==False):
            answer = max(answer, dfs(i, adj, vis))
    return answer
 
# Driver Code
if __name__ == '__main__':
    n = 8
    A = [2, 3, 6, 7, 4, 12, 21, 39]
    print(maximumComponentSize(A, n))
 
# This code is contributed by Bhupendra_Singh




// C# program to implement
// the above approach
using System;
using System.Collections.Generic;
class GFG{
 
static int dfs(int u,
               List<int> []adj,
               int []vis)
{   
  // Mark this node as visited
  vis[u] = 1;
  int componentSize = 1;
 
  // Apply dfs and add nodes belonging
  // to this component
  foreach(int it in adj[u])
  {
    if (vis[it] == 0)
    {
      componentSize += dfs(it,
                           adj, vis);
    }
  }
  return componentSize;
}
 
  static int maximumComponentSize(int []a,
                                  int n)
  {   
    // Create graph and store in adjacency
    // list form
 
    List<int> []adj = new List<int>[n];
    for(int i = 0; i < adj.Length; i++)
      adj[i] = new List<int>();
 
    // Iterate over all pair of nodes
    for(int i = 0; i < n; i++)
    {
      for(int j = i + 1; j < n; j++)
      {           
        // If not co-prime
        if (__gcd(a[i], a[j]) > 1)
 
          // Build undirected graph
          adj[i].Add(j);
 
        adj[j].Add(i);
      }
    }
    int answer = 0;
 
    // Visited array for dfs
    int []vis = new int[n];
    for(int k = 0; k < n; k++)
    {
      vis[k] = 0;
    }
 
    for(int i = 0; i < n; i++)
    {
      if (vis[i] == 0)
      {
        answer = Math.Max(answer,
                          dfs(i,
                              adj, vis));
      }
    }
    return answer;
}
 
static int __gcd(int a, int b)
  return b == 0 ? a :
         __gcd(b, a % b);    
}
 
// Driver Code
public static void Main(String[] args)
{
  int n = 8;
  int []A = {2, 3, 6, 7,
             4, 12, 21, 39};
  Console.Write(maximumComponentSize(A, n));
}
}
 
// This code is contributed by shikhasingrajput




<script>
 
// Javascript program to implement
// the above approach
 
function dfs(u, adj, vis)
{  
      // Mark this node as visited
    vis[u] = 1;
    let componentSize = 1;
  
      // Apply dfs and add nodes belonging
      // to this component
    for(let it in adj[u])
    {
          if (vis[it] == 0)
        {
              componentSize += dfs(it,
                           adj, vis);
        }
      }
      return componentSize;
}
  
function maximumComponentSize(a, n)
{  
    // Create graph and store in adjacency
    // list form
  
    let adj = new Array(n);
    for (var i = 0; i < adj.length; i++) {
        adj[i] = new Array(2);
    }
    for (var i = 0; i < adj.length; i++) {
        for (var j = 0; j < adj.length; j++) {
            adj[i][j] = 0;
        }
    }
  
    // Iterate over all pair of nodes
    for(let i = 0; i < n; i++)
    {
        for(let j = i + 1; j < n; j++)
          {          
            // If not co-prime
            if (__gcd(a[i], a[j]) > 1)
  
              // Build undirected graph
              adj[i].push(j);
  
            adj[j].push(i);
          }
    }
    let answer = 0;
  
    // Visited array for dfs
    let vis = Array.from({length: n}, (_, i) => 0);
    for(let k = 0; k < n; k++)
    {
          vis[k] = 0;
    }
  
    for(let i = 0; i < n; i++)
    {
          if (vis[i] == 0)
          {
            answer = Math.max(answer,
                          dfs(i,
                              adj, vis));
          }
       }
    return answer;
}
  
function __gcd(a, b)
{
      return b == 0 ? a :
         __gcd(b, a % b);   
}
 
// Driver Code
     
    let n = 8;
    let A = [2, 3, 6, 7, 4, 12, 21, 39];
      
    document.write(maximumComponentSize(A, n));
                
</script>

Output:

8

Time complexity: O(N2)

Auxiliary Space: O(N)

Efficient Approach

par[i] -> represents the parent of node i 
size[i] -> represents the size of the component node i belongs to 
id[p] -> represents which node prime number p was first seen as a factor of A[i] 

Below is the implementation of the above approach:




#include <bits/stdc++.h>
  
using namespace std;
  
// smallest prime factor
int spf[100005];
  
// Sieve of Eratosthenes
void sieve()
{
    for (int i = 2; i < 100005; i++) {
        // is spf[i] = 0, then it's prime
        if (spf[i] == 0) {
            spf[i] = i;
 
            for (int j = 2 * i; j < 100005; j += i) {
 
                // smallest prime factor of all multiples is i
                if (spf[j] == 0)
                    spf[j] = i;
            }
        }
    }
}
  
// Prime factorise n,
// and store prime factors in set s
void factorize(int n, set<int>& s)
{
  
    while (n > 1) {
        int z = spf[n];
        s.insert(z);
        while (n % z == 0)
            n /= z;
    }
}
  
// for implementing DSU
int id[100005];
int par[100005];
int sizeContainer[100005];
  
// root of component of node i
int root(int i)
{
    if (par[i] == i)
        return i;
    // finding root as well as applying
    // path compression
    else
        return par[i] = root(par[i]);
}
  
// merging two components
void merge(int a, int b)
{
  
    // find roots of both components
    int p = root(a);
    int q = root(b);
  
    // if already belonging to the same component
    if (p == q)
        return;
  
    // Union by rank, the rank in this case is
    // sizeContainer of the component.
    // Smaller sizeContainer will be merged into
    // larger, so the larger's root will be
    // final root
    if (sizeContainer[p] > sizeContainer[q])
        swap(p, q);
  
    par[p] = q;
    sizeContainer[q] += sizeContainer[p];
}
  
// Function to find the maximum sized container
int maximumComponentsizeContainer(int a[], int n)
{
  
    // intitalise the parents,
    // and component sizeContainer
    for (int i = 0; i < 100005; i++) {
        // initially all component sizeContainers are 1
        // ans each node it parent of itself
        par[i] = i;
        sizeContainer[i] = 1;
    }
  
    sieve();
  
    for (int i = 0; i < n; i++) {
        // store prime factors of a[i] in s
        set<int> s;
        factorize(a[i], s);
  
        for (auto it : s) {
            // if this prime is seen as a factor
            // for the first time
            if (id[it] == 0)
                id[it] = i + 1;
            // if not then merge with that component
            // in which this prime was previously seen
            else
                merge(i + 1, id[it]);
        }
    }
  
    int answer = 0;
 
    // maximum of sizeContainer of all components
    for (int i = 0; i < n; i++)
        answer = max(answer, sizeContainer[i]);
  
    return answer;
}
 
// Driver Code
int main()
{
    int n = 8;
    int A[] = { 2, 3, 6, 7, 4, 12, 21, 39 };
  
    cout << maximumComponentsizeContainer(A, n);
  
    return 0;
}




// Java program to implement
// the above approach
import java.util.*;
class GFG{
  
// smallest prime factor
static int []spf = new int[100005];
  
// Sieve of Eratosthenes
static void sieve()
{
    for (int i = 2; i < 100005; i++)
    {
        // is spf[i] = 0, then it's prime
        if (spf[i] == 0)
        {
            spf[i] = i;
            for (int j = 2 * i; j < 100005; j += i)
            {
                // smallest prime factor of all
                // multiples is i
                if (spf[j] == 0)
                    spf[j] = i;
            }
        }
    }
}
  
// Prime factorise n,
// and store prime factors in set s
static void factorize(int n, HashSet<Integer> s)
{
    while (n > 1)
    {
        int z = spf[n];
        s.add(z);
        while (n % z == 0)
            n /= z;
    }
}
  
// for implementing DSU
static int []id = new int[100005];
static int []par = new int[100005];
static int []sizeContainer = new int[100005];
  
// root of component of node i
static int root(int i)
{
    if (par[i] == i)
        return i;
    // finding root as well as applying
    // path compression
    else
        return par[i] = root(par[i]);
}
  
// merging two components
static void merge(int a, int b)
{
    // find roots of both components
    int p = root(a);
    int q = root(b);
  
    // if already belonging to the same component
    if (p == q)
        return;
  
    // Union by rank, the rank in this case is
    // sizeContainer of the component.
    // Smaller sizeContainer will be merged into
    // larger, so the larger's root will be
    // final root
    if (sizeContainer[p] > sizeContainer[q])
    {
        p = p + q;
        q = p - q;
        p = p - q;
    }
    par[p] = q;
    sizeContainer[q] += sizeContainer[p];
}
  
// Function to find the maximum sized container
static int maximumComponentsizeContainer(int a[],
                                         int n)
{
    // intitalise the parents,
    // and component sizeContainer
    for (int i = 0; i < 100005; i++)
    {
        // initially all component sizeContainers are 1
        // ans each node it parent of itself
        par[i] = i;
        sizeContainer[i] = 1;
    }
    sieve();
  
    for (int i = 0; i < n; i++)
    {
        // store prime factors of a[i] in s
        HashSet<Integer> s = new HashSet<Integer>();
        factorize(a[i], s);
  
        for (int it : s)
        {
            // if this prime is seen as a factor
            // for the first time
            if (id[it] == 0)
                id[it] = i + 1;
            // if not then merge with that component
            // in which this prime was previously seen
            else
                merge(i + 1, id[it]);
        }
    }
    int answer = 0;
 
    // maximum of sizeContainer of all components
    for (int i = 0; i < n; i++)
        answer = Math.max(answer, sizeContainer[i]);
  
    return answer;
}
 
// Driver Code
public static void main(String[] args)
{
    int n = 8;
    int A[] = {2, 3, 6, 7,
               4, 12, 21, 39};
    System.out.print(
           maximumComponentsizeContainer(A, n));
}
}
 
// This code is contributed by shikhasingrajput




# Python3 program to implement
# the above approach
   
# smallest prime factor
spf = [0 for i in range(100005)]
   
# Sieve of Eratosthenes
def sieve():
 
    for i in range(2, 100005):
     
        # is spf[i] = 0, then it's prime
        if (spf[i] == 0):
         
            spf[i] = i;
            for j in range(2 * i, 100005, i):
             
                # smallest prime factor of all
                # multiples is i
                if (spf[j] == 0):
                    spf[j] = i;
              
# Prime factorise n,
# and store prime factors in set s
def factorize(n, s):
    while (n > 1):  
        z = spf[n];
        s.add(z);
        while (n % z == 0):
            n //= z;
      
# for implementing DSU
id = [0 for i in range(100005)]
par = [0 for i in range(100005)]
sizeContainer = [0 for i in range(100005)]
   
# root of component of node i
def root(i):
 
    if (par[i] == i):
        return i;
       
    # finding root as well as applying
    # path compression
    else:
        return root(par[i]);
        return par[i]
  
# merging two components
def merge(a, b):
 
    # find roots of both components
    p = root(a);
    q = root(b);
   
    # if already belonging to the same component
    if (p == q):
        return;
   
    # Union by rank, the rank in this case is
    # sizeContainer of the component.
    # Smaller sizeContainer will be merged into
    # larger, so the larger's root will be
    # final root
    if (sizeContainer[p] > sizeContainer[q]):   
        p = p + q;
        q = p - q;
        p = p - q;  
    par[p] = q;
    sizeContainer[q] += sizeContainer[p];
   
# Function to find the maximum sized container
def maximumComponentsizeContainer(a, n):
 
    # intitalise the parents,
    # and component sizeContainer
    for i in range(100005):
         
        # initially all component sizeContainers are 1
        # ans each node it parent of itself
        par[i] = i;
        sizeContainer[i] = 1;
    sieve();
     
    for i in range(n):
 
        # store prime factors of a[i] in s
        s = set()       
        factorize(a[i], s); 
        for it in s:
 
            # if this prime is seen as a factor
            # for the first time
            if (id[it] == 0):
                id[it] = i + 1;
                 
            # if not then merge with that component
            # in which this prime was previously seen
            else:
                merge(i + 1, id[it]);       
    answer = 0;
  
    # maximum of sizeContainer of all components
    for i in range(n): 
        answer = max(answer, sizeContainer[i]);
    return answer;
  
# Driver Code
if __name__=='__main__':
     
    n = 8;
    A = [2, 3, 6, 7, 4, 12, 21, 39]
    print(maximumComponentsizeContainer(A, n));
 
# This code is contributed by Pratham76




// C# program to implement
// the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
// Smallest prime factor
static int []spf = new int[100005];
 
// Sieve of Eratosthenes
static void sieve()
{
    for(int i = 2; i < 100005; i++)
    {
         
        // Is spf[i] = 0, then it's prime
        if (spf[i] == 0)
        {
            spf[i] = i;
            for(int j = 2 * i; j < 100005; j += i)
            {
                 
                // Smallest prime factor of all
                // multiples is i
                if (spf[j] == 0)
                    spf[j] = i;
            }
        }
    }
}
 
// Prime factorise n, and store
// prime factors in set s
static void factorize(int n, HashSet<int> s)
{
    while (n > 1)
    {
        int z = spf[n];
        s.Add(z);
         
        while (n % z == 0)
            n /= z;
    }
}
 
// For implementing DSU
static int []id = new int[100005];
static int []par = new int[100005];
static int []sizeContainer = new int[100005];
 
// Root of component of node i
static int root(int i)
{
    if (par[i] == i)
        return i;
         
    // Finding root as well as applying
    // path compression
    else
        return par[i] = root(par[i]);
}
 
// Merging two components
static void merge(int a, int b)
{
     
    // Find roots of both components
    int p = root(a);
    int q = root(b);
 
    // If already belonging to
    // the same component
    if (p == q)
        return;
 
    // Union by rank, the rank in this case is
    // sizeContainer of the component.
    // Smaller sizeContainer will be merged into
    // larger, so the larger's root will be
    // readonly root
    if (sizeContainer[p] > sizeContainer[q])
    {
        p = p + q;
        q = p - q;
        p = p - q;
    }
    par[p] = q;
    sizeContainer[q] += sizeContainer[p];
}
 
// Function to find the maximum sized container
static int maximumComponentsizeContainer(int []a,
                                         int n)
{
     
    // Initialise the parents,
    // and component sizeContainer
    for(int i = 0; i < 100005; i++)
    {
         
        // Initially all component sizeContainers
        // are 1 ans each node it parent of itself
        par[i] = i;
        sizeContainer[i] = 1;
    }
    sieve();
 
    for(int i = 0; i < n; i++)
    {
         
        // Store prime factors of a[i] in s
        HashSet<int> s = new HashSet<int>();
        factorize(a[i], s);
 
        foreach(int it in s)
        {
             
            // If this prime is seen as a factor
            // for the first time
            if (id[it] == 0)
                id[it] = i + 1;
                 
            // If not then merge with that component
            // in which this prime was previously seen
            else
                merge(i + 1, id[it]);
        }
    }
    int answer = 0;
 
    // Maximum of sizeContainer of all components
    for(int i = 0; i < n; i++)
        answer = Math.Max(answer, sizeContainer[i]);
 
    return answer;
}
 
// Driver Code
public static void Main(String[] args)
{
    int n = 8;
    int []A = { 2, 3, 6, 7,
                4, 12, 21, 39 };
                 
    Console.Write(
        maximumComponentsizeContainer(A, n));
}
}
 
// This code is contributed by Princi Singh




<script>
 
  
// smallest prime factor
var spf = Array(100005).fill(0);
  
// Sieve of Eratosthenes
function sieve()
{
    for (var i = 2; i < 100005; i++) {
        // is spf[i] = 0, then it's prime
        if (spf[i] == 0) {
            spf[i] = i;
 
            for (var j = 2 * i; j < 100005; j += i) {
 
                // smallest prime factor of all multiples is i
                if (spf[j] == 0)
                    spf[j] = i;
            }
        }
    }
}
  
// Prime factorise n,
// and store prime factors in set s
function factorize(n, s)
{
  
    while (n > 1) {
        var z = spf[n];
        s.add(z);
        while (n % z == 0)
            n = parseInt(n/z);
    }
    return s;
}
  
// for implementing DSU
var id = Array(100005).fill(0);
var par =Array(100005).fill(0);
var sizeContainer = Array(100005).fill(0);
  
// root of component of node i
function root(i)
{
    if (par[i] == i)
        return i;
    // finding root as well as applying
    // path compression
    else
        return par[i] = root(par[i]);
}
  
// merging two components
function merge(a, b)
{
  
    // find roots of both components
    var p = root(a);
    var q = root(b);
  
    // if already belonging to the same component
    if (p == q)
        return;
  
    // Union by rank, the rank in this case is
    // sizeContainer of the component.
    // Smaller sizeContainer will be merged into
    // larger, so the larger's root will be
    // final root
    if (sizeContainer[p] > sizeContainer[q])
    {
        [p, q] = [q, p]
    }
  
    par[p] = q;
    sizeContainer[q] += sizeContainer[p];
}
  
// Function to find the maximum sized container
function maximumComponentsizeContainer(a, n)
{
  
    // intitalise the parents,
    // and component sizeContainer
    for (var i = 0; i < 100005; i++) {
        // initially all component sizeContainers are 1
        // ans each node it parent of itself
        par[i] = i;
        sizeContainer[i] = 1;
    }
  
    sieve();
  
    for (var i = 0; i < n; i++) {
        // store prime factors of a[i] in s
        var s = new Set();
        s = factorize(a[i], s);
         
        s.forEach(it => {
             
            // if this prime is seen as a factor
            // for the first time
            if (id[it] == 0)
                id[it] = i + 1;
            // if not then merge with that component
            // in which this prime was previously seen
            else
                merge(i + 1, id[it]);
        });
    }
  
    var answer = 0;
 
    // maximum of sizeContainer of all components
    for (var i = 0; i < n; i++)
        answer = Math.max(answer, sizeContainer[i]);
  
    return answer;
}
 
// Driver Code
var n = 8;
var A = [2, 3, 6, 7, 4, 12, 21, 39];
 
document.write( maximumComponentsizeContainer(A, n));
 
 
</script>

Output:

 8

Time Complexity : O(N * log(max(A)))  

Auxiliary Space: O(105)


Article Tags :