Open In App

Find all cliques of size K in an undirected graph

Given an undirected graph with N nodes and E edges and a value K, the task is to print all set of nodes which form a K size clique
A clique is a complete subgraph of a graph.
Examples: 
 

Input: N = 5, edges[] = { {1, 2}, {2, 3}, {3, 1}, {4, 3}, {4, 5}, {5, 3} }, K = 3 
Output: 1 2 3, 3 4 5 
Explanation: Clearly from the image, 1->2->3 and 3->4->5 are the two complete subgraphs. 
Input: N = 4, edges[] = { {1, 2}, {2, 3}, {3, 1}, {4, 3} }, k = 3 
Output: 1 2 3 
Explanation: Subgraph 1-> 2->3 forms a complete subgraph from the given graph. 
 

 

Approach: The idea is to use recursion to solve the above problem. All the vertices whose degree is greater than or equal to (K-1) are found and checked which subset of K vertices form a clique. When another edge is added to the present list, it is checked if by adding that edge, the list still forms a clique or not. 
The following steps can be followed to compute the result: 
 

Below is the implementation of the above approach: 
 




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
 
const int MAX = 100;
 
// Stores the vertices
int store[MAX], n;
 
// Graph
int graph[MAX][MAX];
 
// Degree of the vertices
int d[MAX];
 
// Function to check if the given set of vertices
// in store array is a clique or not
bool is_clique(int b)
{
    // Run a loop for all the set of edges
    // for the select vertex
    for (int i = 1; i < b; i++) {
        for (int j = i + 1; j < b; j++)
 
            // If any edge is missing
            if (graph[store[i]][store[j]] == 0)
                return false;
    }
    return true;
}
 
// Function to print the clique
void print(int n)
{
    for (int i = 1; i < n; i++)
        cout << store[i] << " ";
    cout << ", ";
}
 
// Function to find all the cliques of size s
void findCliques(int i, int l, int s)
{
    // Check if any vertices from i+1 can be inserted
    for (int j = i + 1; j <= n - (s - l); j++)
 
        // If the degree of the graph is sufficient
        if (d[j] >= s - 1) {
 
            // Add the vertex to store
            store[l] = j;
 
            // If the graph is not a clique of size k
            // then it cannot be a clique
            // by adding another edge
            if (is_clique(l + 1))
 
                // If the length of the clique is
                // still less than the desired size
                if (l < s)
 
                    // Recursion to add vertices
                    findCliques(j, l + 1, s);
 
                // Size is met
                else
                    print(l + 1);
        }
}
 
// Driver code
int main()
{
    int edges[][2] = { { 1, 2 },
                       { 2, 3 },
                       { 3, 1 },
                       { 4, 3 },
                       { 4, 5 },
                       { 5, 3 } },
        k = 3;
    int size = sizeof(edges) / sizeof(edges[0]);
    n = 5;
 
    for (int i = 0; i < size; i++) {
        graph[edges[i][0]][edges[i][1]] = 1;
        graph[edges[i][1]][edges[i][0]] = 1;
        d[edges[i][0]]++;
        d[edges[i][1]]++;
    }
 
    findCliques(0, 1, k);
 
    return 0;
}




// Java implementation of the approach
class GFG
{
 
static int MAX = 100;
 
// Stores the vertices
static int []store = new int[MAX];
static int n;
 
// Graph
static int [][]graph = new int [MAX][MAX];
 
// Degree of the vertices
static int []d = new int[MAX];
 
// Function to check if the given set of vertices
// in store array is a clique or not
static boolean is_clique(int b)
{
    // Run a loop for all the set of edges
    // for the select vertex
    for (int i = 1; i < b; i++)
    {
        for (int j = i + 1; j < b; j++)
 
            // If any edge is missing
            if (graph[store[i]][store[j]] == 0)
                return false;
    }
    return true;
}
 
// Function to print the clique
static void print(int n)
{
    for (int i = 1; i < n; i++)
        System.out.print(store[i] + " ");
    System.out.print(", ");
}
 
// Function to find all the cliques of size s
static void findCliques(int i, int l, int s)
{
    // Check if any vertices from i+1 can be inserted
    for (int j = i + 1; j <= n - (s - l); j++)
 
        // If the degree of the graph is sufficient
        if (d[j] >= s - 1)
        {
 
            // Add the vertex to store
            store[l] = j;
 
            // If the graph is not a clique of size k
            // then it cannot be a clique
            // by adding another edge
            if (is_clique(l + 1))
 
                // If the length of the clique is
                // still less than the desired size
                if (l < s)
 
                    // Recursion to add vertices
                    findCliques(j, l + 1, s);
 
                // Size is met
                else
                    print(l + 1);
        }
}
 
// Driver code
public static void main(String[] args)
{
    int edges[][] = { { 1, 2 },
                    { 2, 3 },
                    { 3, 1 },
                    { 4, 3 },
                    { 4, 5 },
                    { 5, 3 } },
    k = 3;
    int size = edges.length;
    n = 5;
 
    for (int i = 0; i < size; i++)
    {
        graph[edges[i][0]][edges[i][1]] = 1;
        graph[edges[i][1]][edges[i][0]] = 1;
        d[edges[i][0]]++;
        d[edges[i][1]]++;
    }
 
    findCliques(0, 1, k);
}
}
 
// This code is contributed by 29AjayKumar




# Python3 implementation of the approach
import numpy as np
 
MAX = 100;
 
# Stores the vertices
store = [0]* MAX;
 
# Graph
graph = np.zeros((MAX, MAX));
 
# Degree of the vertices
d = [0] * MAX;
 
# Function to check if the given set of vertices
# in store array is a clique or not
def is_clique(b) :
 
    # Run a loop for all the set of edges
    # for the select vertex
    for i in range(1, b) :
        for j in range(i + 1, b) :
 
            # If any edge is missing
            if (graph[store[i]][store[j]] == 0) :
                return False;
     
    return True;
 
# Function to print the clique
def print_cli(n) :
 
    for i in range(1, n) :
        print(store[i], end = " ");
    print(",", end=" ");
 
# Function to find all the cliques of size s
def findCliques(i, l, s) :
 
    # Check if any vertices from i+1 can be inserted
    for j in range( i + 1, n -(s - l) + 1) :
 
        # If the degree of the graph is sufficient
        if (d[j] >= s - 1) :
 
            # Add the vertex to store
            store[l] = j;
 
            # If the graph is not a clique of size k
            # then it cannot be a clique
            # by adding another edge
            if (is_clique(l + 1)) :
 
                # If the length of the clique is
                # still less than the desired size
                if (l < s) :
 
                    # Recursion to add vertices
                    findCliques(j, l + 1, s);
 
                # Size is met
                else :
                    print_cli(l + 1);
 
# Driver code
if __name__ == "__main__" :
 
    edges = [ [ 1, 2 ],
              [ 2, 3 ],
              [ 3, 1 ],
              [ 4, 3 ],
              [ 4, 5 ],
              [ 5, 3 ] ];
    k = 3;
    size = len(edges);
    n = 5;
 
    for i in range(size) :
        graph[edges[i][0]][edges[i][1]] = 1;
        graph[edges[i][1]][edges[i][0]] = 1;
        d[edges[i][0]] += 1;
        d[edges[i][1]] += 1;
     
 
    findCliques(0, 1, k);
 
# This code is contributed by AnkitRai01




// C# implementation of the approach
using System;
 
class GFG
{
 
    static int MAX = 100;
     
    // Stores the vertices
    static int []store = new int[MAX];
    static int n;
     
    // Graph
    static int [,]graph = new int [MAX, MAX];
     
    // Degree of the vertices
    static int []d = new int[MAX];
     
    // Function to check if the given set of vertices
    // in store array is a clique or not
    static bool is_clique(int b)
    {
        // Run a loop for all the set of edges
        // for the select vertex
        for (int i = 1; i < b; i++)
        {
            for (int j = i + 1; j < b; j++)
     
                // If any edge is missing
                if (graph[store[i], store[j]] == 0)
                    return false;
        }
        return true;
    }
     
    // Function to print the clique
    static void print(int n)
    {
        for (int i = 1; i < n; i++)
            Console.Write(store[i] + " ");
        Console.Write(", ");
    }
     
    // Function to find all the cliques of size s
    static void findCliques(int i, int l, int s)
    {
        // Check if any vertices from i+1 can be inserted
        for (int j = i + 1; j <= n - (s - l); j++)
     
            // If the degree of the graph is sufficient
            if (d[j] >= s - 1)
            {
     
                // Add the vertex to store
                store[l] = j;
     
                // If the graph is not a clique of size k
                // then it cannot be a clique
                // by adding another edge
                if (is_clique(l + 1))
     
                    // If the length of the clique is
                    // still less than the desired size
                    if (l < s)
     
                        // Recursion to add vertices
                        findCliques(j, l + 1, s);
     
                    // Size is met
                    else
                        print(l + 1);
            }
    }
     
    // Driver code
    public static void Main()
    {
        int [,]edges = { { 1, 2 },
                        { 2, 3 },
                        { 3, 1 },
                        { 4, 3 },
                        { 4, 5 },
                        { 5, 3 } };
        int k = 3;
        int size = edges.GetLength(0);
        n = 5;
     
        for (int i = 0; i < size; i++)
        {
            graph[edges[i, 0], edges[i, 1]] = 1;
            graph[edges[i, 1], edges[i, 0]] = 1;
            d[edges[i, 0]]++;
            d[edges[i, 1]]++;
        }
     
        findCliques(0, 1, k);
    }
}
 
// This code is contributed by AnkitRai01




<script>
    // JavaScript implementation of the approach
    const MAX = 100;
 
    // Stores the vertices
    let store = new Array(MAX).fill(0), n = 0;
     
    // Graph
    let graph = new Array(MAX).fill(0).map(() => new Array(MAX).fill(0));
 
    // Degree of the vertices
    let d = new Array(MAX).fill(0);
 
    // Function to check if the given set of vertices
    // in store array is a clique or not
    const is_clique = (b) => {
     
        // Run a loop for all the set of edges
        // for the select vertex
        for (let i = 1; i < b; i++) {
            for (let j = i + 1; j < b; j++)
 
                // If any edge is missing
                if (graph[store[i]][store[j]] == 0)
                    return false;
        }
        return true;
    }
 
    // Function to print the clique
    const print = (n) => {
        for (let i = 1; i < n; i++)
            document.write(`${store[i]} `);
        document.write(", ");
    }
 
    // Function to find all the cliques of size s
    const findCliques = (i, l, s) => {
     
        // Check if any vertices from i+1 can be inserted
        for (let j = i + 1; j <= n - (s - l); j++)
 
            // If the degree of the graph is sufficient
            if (d[j] >= s - 1) {
 
                // Add the vertex to store
                store[l] = j;
 
                // If the graph is not a clique of size k
                // then it cannot be a clique
                // by adding another edge
                if (is_clique(l + 1))
 
                    // If the length of the clique is
                    // still less than the desired size
                    if (l < s)
 
                        // Recursion to add vertices
                        findCliques(j, l + 1, s);
 
                    // Size is met
                    else
                        print(l + 1);
            }
    }
 
    // Driver code
    const edges = [
        [1, 2],
        [2, 3],
        [3, 1],
        [4, 3],
        [4, 5],
        [5, 3]
    ];
     
    let k = 3;
    let size = edges.length;
    n = 5;
 
    for (let i = 0; i < size; i++) {
        graph[edges[i][0]][edges[i][1]] = 1;
        graph[edges[i][1]][edges[i][0]] = 1;
        d[edges[i][0]]++;
        d[edges[i][1]]++;
    }
 
    findCliques(0, 1, k);
     
    // This code is contributed by rakeshsahni
 
</script>

Output: 
1 2 3 , 3 4 5 ,

 

Time Complexity: O(2^(n/2)) where n is the number of vertices in the graph. The worst case occurs when the graph is a complete graph and all cliques of the given size are present.

Space Complexity : O(n^2) to store the graph


Article Tags :