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:Â Â
C++
#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 Codeint main(){    int n = 8;    int A[] = { 2, 3, 6, 7, 4, 12, 21, 39 };    cout << maximumComponentSize(A, n);    return 0;} |
Java
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 Codepublic 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 |
Python3
from math import gcddef 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 Codeif __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#
// C# program to implement // the above approachusing 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 Codepublic 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 |
Javascript
<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
- For any two numbers to be non-co-prime, they must have at least one common factor. So, instead of traversing through all the pairs, it’s better to prime factorize each node value. The idea is to then club together numbers with common factors as a single group.
- Prime factorization can be done efficiently using the Sieve of Eratosthenes. For clubbing together of nodes we will use a Disjoint set data structure (Union by Rank and Path Compression).
- The following information will be stored :
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]Â
- For each node value, we will factorize and store the prime factors in set S. Iterate each element of S. If the prime number is seen for the first time as a factor of some number (id[p] is zero), then mark this prime id with the current index. If this prime has been marked, then simply merge this node with that of id[p].
This way, all nodes will belong to some component finally, and size[i] will be the size of component node i belongs to.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>  using namespace std;  // smallest prime factorint spf[100005];  // Sieve of Eratosthenesvoid 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 svoid factorize(int n, set<int>& s){      while (n > 1) {        int z = spf[n];        s.insert(z);        while (n % z == 0)            n /= z;    }}  // for implementing DSUint id[100005];int par[100005];int sizeContainer[100005];  // root of component of node iint 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 componentsvoid 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 containerint 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 Codeint main(){Â Â Â Â int n = 8;Â Â Â Â int A[] = { 2, 3, 6, 7, 4, 12, 21, 39 };Â Â Â Â Â Â cout << maximumComponentsizeContainer(A, n);Â Â Â Â Â Â return 0;} |
Java
// Java program to implement // the above approachimport java.util.*;class GFG{  // smallest prime factorstatic int []spf = new int[100005];  // Sieve of Eratosthenesstatic 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 sstatic 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 DSUstatic int []id = new int[100005];static int []par = new int[100005];static int []sizeContainer = new int[100005];  // root of component of node istatic 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 componentsstatic 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 containerstatic 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 Codepublic 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
# Python3 program to implement # the above approach   # smallest prime factorspf = [0 for i in range(100005)]   # Sieve of Eratosthenesdef 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 sdef factorize(n, s):    while (n > 1):          z = spf[n];        s.add(z);        while (n % z == 0):            n //= z;      # for implementing DSUid = [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 idef 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 componentsdef 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 containerdef 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 Codeif __name__=='__main__':         n = 8;    A = [2, 3, 6, 7, 4, 12, 21, 39]    print(maximumComponentsizeContainer(A, n)); Â
# This code is contributed by Pratham76 |
C#
// C# program to implement // the above approachusing System;using System.Collections.Generic;Â
class GFG{Â
// Smallest prime factorstatic int []spf = new int[100005];Â
// Sieve of Eratosthenesstatic 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 sstatic 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 DSUstatic int []id = new int[100005];static int []par = new int[100005];static int []sizeContainer = new int[100005];Â
// Root of component of node istatic 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 componentsstatic 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 containerstatic 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 Codepublic 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 |
Javascript
<script>Â
  // smallest prime factorvar spf = Array(100005).fill(0);  // Sieve of Eratosthenesfunction 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 sfunction 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 DSUvar id = Array(100005).fill(0);var par =Array(100005).fill(0);var sizeContainer = Array(100005).fill(0);  // root of component of node ifunction 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 componentsfunction 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 containerfunction 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 Codevar 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)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 zambiatek!


