Open In App

Count Permutations so that adjacent elements are neighbours in given Graph

Last Updated : 07 May, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] of integers having N elements and a non-weighted undirected graph having N nodes and M edges. The edges are represented as a list, the task is to count the number of permutations of the array, for which every node of the array, Vi [1 ≤ i ≤ N-1], there exists an edge between the nodes Vi and Vi+1 in the given graph.

Examples:

Input: N = 3, M = 2, arr = {1, 2, 3}, graph = {{3, 1}, {1, 2}}
Output: 2
Explanation: All possible permutations of the array are as follows:

  • {1, 2, 3}: There is an edge between 1 and 2 in the graph but not between 2 and 3.
  • {2, 1, 3}: There is an edge between (2, 1) and (1, 3) in the graph.
  • {3, 1, 2}: There is an edge between (3, 1) and (1, 2) in the graph.

Out of the 3 possible permutations,  2 satisfies the given conditions. Therefore, the answer is 2.

Input: N = 2, M = 1, arr = {1, 1}, graph = {{1, 2}}
Output: 0
Explanation: There is no such permutation of the array that follows the given conditions. 

Approach: To solve the problem using Dynamic Programming + Bitmasking follow the below idea:

We will be trying to calculate the count of permutations which is ending at node arr[i] and where all elements are considered. We will find such count for all i from 0 to N and in the end will add all such count of permutations in our answer. Here In our mask if jth setbit is on this implies node arr[j] is already considered in our permutation till now. We will be using dynamic programming with bitmasking as there could be possibility that we have considered the same set of elements up to now in our permutation and it is ending at a same node so to stop recalculation we will store such values.

Steps that were to follow the above approach:

  • Create a 2d array, dp, and initialize it with 0. Here dp[i][j] is used to store the number of permutations that end at the node arr[i] and all the array indices corresponding to the set bits in the number j have been visited.
  • Create a 2d array, adj, and initialize it with 0. Here if adj[i][j] is 1 then there is an edge between node i and j else there isn’t.
  • Update the value of dp to 1 in case of j=1<<i as there will be one permutation ending at i and of size 1.
  • Run three loops, the first loop will be for all possible values of the mask, In the second loop we will be iterating, i, over 0 to N, and in the third loop, we will be iterating, j, over 0 to N. Second loop will be inside first and third will be inside second.
    • Now inside the third loop if there is an edge between i and j and i do not equal to j as well as arr[i] and arr[j] are not equal and if j is already not taken in the mask then we will update our dp[i][mask]
      • dp[i][mask] += dp[j][mask ^ (1 << i)]
  • Initialize ans variable with 0. 
  • Run a loop for i equals 0 to N where we will be adding dp[i][mask] in ans where dp[i][mask] is the count of all permutations that ends at node arr[i] and all elements are considered i.e. 
    mask = (1 << N) – 1.
  • Return ans.

Below is the code to implement the above approach:

C++




// C++ code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Define the countPermutations function
// that takes in N, M, arr, and
// graph as arguments
long long int countPermutations(int N, int M,
                                vector<int> arr,
                                vector<vector<int> > graph)
{
 
    // Create a 2D vector dp of size Nx2^N
    // and initialize all values to 0
    vector<vector<long long int> > dp(
        N, vector<long long int>(1 << N, 0));
 
    // Set the base cases where each
    // element i is used on its own,
    // represented by  a bitmask with
    // only the ith bit set to 1
    for (int i = 0; i < N; i++) {
        dp[i][1 << i] = 1;
    }
 
    // Create an adjacency matrix adj of
    // size NxN to represent the edges
    // in the graph
    vector<vector<int> > adj(N, vector<int>(N, 0));
    for (vector<int> edge : graph) {
 
        // Set the corresponding entries
        // in the adjacency matrix to 1 to
        // represent the edges in the graph
        adj[edge[0] - 1][edge[1] - 1] = 1;
        adj[edge[1] - 1][edge[0] - 1] = 1;
    }
 
    // Loop over all possible bitmasks
    // of length N
    for (int bitmask = 1; bitmask < (1 << N); bitmask++) {
 
        // Loop over all elements i
        // in the bitmask
        for (int i = 0; i < N; i++) {
 
            // Check if element i is used
            // in the bitmask
            if ((1 & (bitmask >> i))) {
 
                // Loop over all other
                // elements j in the
                // bitmask
                for (int j = 0; j < N; j++) {
 
                    // Check if element j
                    // is adjacent to element
                    // i in the graph, has a
                    // different value in arr,
                    // and is also used in
                    // the bitmask
                    if (j != i && arr[j] != arr[i]
                        && (1 & (bitmask >> j))
                        && adj[arr[i] - 1][arr[j] - 1]) {
                        // update the count
                        // of permutations that
                        // end with element i
                        // and have the same set
                        // of used elements as
                        // the current bitmask
                        // by adding the count of
                        // permutations that end
                        // with element j and
                        // have the set of used
                        // elements represented
                        // by the bitmask with
                        // the ith bit flipped
                        // from 1 to 0
                        dp[i][bitmask]
                            += dp[j][bitmask ^ (1 << i)];
                    }
                }
            }
        }
    }
 
    // Sum up the counts of permutations
    // that end with each element i and
    // have used all N elements,
    // represented by the bitmask with
    // all N bits set to 1
    long long int ans = 0;
    for (int i = 0; i < N; i++) {
        ans += dp[i][(1 << N) - 1];
    }
 
    // Return the total count of required
    // permutations
    return ans;
}
 
// Driver's code
int main()
{
 
    // set the values of N, M, arr,
    // and graph
    int N = 3, M = 2;
    vector<int> arr = { 1, 2, 3 };
    vector<vector<int> > graph = { { 3, 1 }, { 1, 2 } };
 
    // Call the countPermutations function
    // with the given arguments and
    // print the result
    long long int ans = countPermutations(N, M, arr, graph);
    cout << ans;
}


Java




// Java code to implement the approach
import java.util.*;
 
public class GFG
{
 
  // Define the countPermutations function
  // that takes in N, M, arr, and
  // graph as arguments
  public static long
    countPermutations(int N, int M, List<Integer> arr,
                      List<List<Integer> > graph)
  {
     
    // Create a 2D vector dp of size Nx2^N
    // and initialize all values to 0
    List<List<Long> > dp = new ArrayList<>();
 
    for (int i = 0; i < N; i++) {
      List<Long> row = new ArrayList<>();
      for (int j = 0; j < (1 << N); j++) {
        row.add(0L);
      }
      dp.add(row);
    }
 
    // Set the base cases where each
    // element i is used on its own,
    // represented by  a bitmask with
    // only the ith bit set to 1
    for (int i = 0; i < N; i++) {
      dp.get(i).set(1 << i, 1L);
    }
 
    // Create an adjacency matrix adj of
    // size NxN to represent the edges
    // in the graph
    int[][] adj = new int[N][N];
 
    for (List<Integer> edge : graph) {
      // Set the corresponding entries
      // in the adjacency matrix to 1 to
      // represent the edges in the graph
      int u = edge.get(0) - 1;
      int v = edge.get(1) - 1;
      adj[u][v] = 1;
      adj[v][u] = 1;
    }
 
    // Loop over all possible bitmasks
    // of length N
    for (int bitmask = 1; bitmask < (1 << N);
         bitmask++) {
      // Loop over all elements i
      // in the bitmask
      for (int i = 0; i < N; i++) {
        // Check if element i is used
        // in the bitmask
        if ((bitmask & (1 << i)) != 0) {
          // Loop over all other
          // elements j in the
          // bitmask
          for (int j = 0; j < N; j++) {
            // Check if element j
            // is adjacent to element
            // i in the graph, has a
            // different value in arr,
            // and is also used in
            // the bitmask
            if (j != i
                && arr.get(j) != arr.get(i)
                && (bitmask & (1 << j)) != 0
                && adj[arr.get(i) - 1]
                [arr.get(j) - 1]
                == 1) {
              // update the count
              // of permutations that
              // end with element i
              // and have the same set
              // of used elements as
              // the current bitmask
              // by adding the count of
              // permutations that end
              // with element j and
              // have the set of used
              // elements represented
              // by the bitmask with
              // the ith bit flipped
              // from 1 to 0
              dp.get(i).set(
                bitmask,
                dp.get(i).get(bitmask)
                + dp.get(j).get(
                  bitmask
                  ^ (1 << i)));
            }
          }
        }
      }
    }
 
    // Sum up the counts of permutations
    // that end with each element i and
    // have used all N elements,
    // represented by the bitmask with
    // all N bits set to 1
    long ans = 0;
    for (int i = 0; i < N; i++) {
      ans += dp.get(i).get((1 << N) - 1);
    }
 
    // Return the total count of required
    // permutations
    return ans;
  }
 
  // Driver's code
  public static void main(String[] args)
  {
    // set the values of N, M, arr,
    // and graph
    int N = 3;
    int M = 2;
    List<Integer> arr
      = new ArrayList<>(Arrays.asList(1, 2, 3));
    List<List<Integer> > graph = new ArrayList<>();
    graph.add(new ArrayList<>(Arrays.asList(3, 1)));
    graph.add(new ArrayList<>(Arrays.asList(1, 2)));
 
    // Call the countPermutations function
    // with the given arguments and
    // print the result
    long ans = countPermutations(N, M, arr, graph);
    System.out.println(ans);
  }
}


Python3




# Python code to implement the approach
 
# Define the countPermutations function
# that takes in N, M, arr, and
# graph as arguments
 
 
def countPermutations(N, M, arr, graph):
 
    # Create a 2D list dp of size Nx2^N
    # and initialize all values to 0
    dp = [[0]*(1 << N) for _ in range(N)]
 
    # Set the base cases where each
    # element i is used on its own,
    # represented by a bitmask with
    # only the ith bit set to 1
    for i in range(N):
        dp[i][1 << i] = 1
 
    # Create an adjacency matrix adj of
    # size NxN to represent the edges
    # in the graph
    adj = [[0]*N for _ in range(N)]
    for edge in graph:
 
        # Set the corresponding entries
        # in the adjacency matrix to 1 to
        # represent the edges in the graph
        adj[edge[0] - 1][edge[1] - 1] = 1
        adj[edge[1] - 1][edge[0] - 1] = 1
 
    # Loop over all possible bitmasks
    # of length N
    for bitmask in range(1, 1 << N):
 
        # Loop over all elements i
        # in the bitmask
        for i in range(N):
 
            # Check if element i is used
            # in the bitmask
            if (1 & (bitmask >> i)):
 
                # Loop over all other
                # elements j in the
                # bitmask
                for j in range(N):
 
                    # Check if element j
                    # is adjacent to element
                    # i in the graph, has a
                    # different value in arr,
                    # and is also used in
                    # the bitmask
                    if j != i and arr[j] != arr[i] and (1 & (bitmask >> j)) and adj[arr[i] - 1][arr[j] - 1]:
 
                        # Update the count
                        # of permutations that
                        # end with element i
                        # and have the same set
                        # of used elements as
                        # the current bitmask
                        # by adding the count of
                        # permutations that end
                        # with element j and
                        # have the set of used
                        # elements represented
                        # by the bitmask with
                        # the ith bit flipped
                        # from 1 to 0
                        dp[i][bitmask] += dp[j][bitmask ^ (1 << i)]
 
    # Sum up the counts of permutations
    # that end with each element i and
    # have used all N elements,
    # represented by the bitmask with
    # all N bits set to 1
    ans = 0
    for i in range(N):
        ans += dp[i][(1 << N) - 1]
 
    # Return the total count of required
    # permutations
    return ans
 
 
# Driver's code
 
# set the values of N, M, arr,
# and graph
N, M = 3, 2
arr = [1, 2, 3]
graph = [[3, 1], [1, 2]]
 
# Call the countPermutations function
# with the given arguments and
# print the result
ans = countPermutations(N, M, arr, graph)
print(ans)


C#




using System;
using System.Collections.Generic;
 
public class GFG {
    static long CountPermutations(int N, int M,
                                  List<int> arr,
                                  List<List<int> > graph)
    {
        // Create a 2D list dp of size Nx2^N and initialize
        // all values to 0
        List<List<long> > dp = new List<List<long> >();
        for (int i = 0; i < N; i++) {
            dp.Add(new List<long>());
            for (int j = 0; j < (1 << N); j++) {
                dp[i].Add(0);
            }
        }
 
        // Set the base cases where each element i is used
        // on its own, represented by a bitmask with only
        // the ith bit set to 1
        for (int i = 0; i < N; i++) {
            dp[i][1 << i] = 1;
        }
 
        // Create an adjacency matrix adj of size NxN to
        // represent the edges in the graph
        int[, ] adj = new int[N, N];
        foreach(List<int> edge in graph)
        {
            // Set the corresponding entries in the
            // adjacency matrix to 1 to represent the edges
            // in the graph
            adj[edge[0] - 1, edge[1] - 1] = 1;
            adj[edge[1] - 1, edge[0] - 1] = 1;
        }
 
        // Loop over all possible bitmasks of length N
        for (int bitmask = 1; bitmask < (1 << N);
             bitmask++) {
            // Loop over all elements i in the bitmask
            for (int i = 0; i < N; i++) {
                // Check if element i is used in the bitmask
                if ((1 & (bitmask >> i)) != 0) {
                    // Loop over all other elements j in the
                    // bitmask
                    for (int j = 0; j < N; j++) {
                        // Check if element j is adjacent to
                        // element i in the graph, has a
                        // different value in arr, and is
                        // also used in the bitmask
                        if (j != i && arr[j] != arr[i]
                            && (1 & (bitmask >> j)) != 0
                            && adj[arr[i] - 1, arr[j] - 1]
                                   != 0) {
                            // update the count of
                            // permutations that end with
                            // element i and have the same
                            // set of used elements as the
                            // current bitmask by adding the
                            // count of permutations that
                            // end with element j and have
                            // the set of used elements
                            // represented by the bitmask
                            // with the ith bit flipped from
                            // 1 to 0
                            dp[i][bitmask]
                                += dp[j]
                                     [bitmask ^ (1 << i)];
                        }
                    }
                }
            }
        }
 
        // Sum up the counts of permutations that end with
        // each element i and have used all N elements,
        // represented by the bitmask with all N bits set to
        // 1
        long ans = 0;
        for (int i = 0; i < N; i++) {
            ans += dp[i][(1 << N) - 1];
        }
 
        // Return the total count of required permutations
        return ans;
    }
 
    static public void Main()
    {
 
        // set the values of N, M, arr,
        // and graph
        int N = 3, M = 2;
        List<int> arr = new List<int>() { 1, 2, 3 };
        List<List<int> > graph = new List<List<int> >() {
            new List<int>() { 3, 1 },
                new List<int>() { 1, 2 }
        };
 
        // Call the CountPermutations function
        // with the given arguments and
        // print the result
        long ans = CountPermutations(N, M, arr, graph);
        Console.WriteLine(ans);
    }
}


Javascript




// Javascript code to implement the approach
 
// Define the countPermutations function
// that takes in N, M, arr, and
// graph as arguments
function countPermutations(N, M, arr, graph) {
// Create a 2D array dp of size Nx2^N
// and initialize all values to 0
let dp = Array.from(Array(N), () => Array(1 << N).fill(0));
// Set the base cases where each
// element i is used on its own,
// represented by a bitmask with
// only the ith bit set to 1
for (let i = 0; i < N; i++) {
    dp[i][1 << i] = 1;
}
 
// Create an adjacency matrix adj of
// size NxN to represent the edges
// in the graph
let adj = Array.from(Array(N), () => Array(N).fill(0));
for (let edge of graph) {
    // Set the corresponding entries
    // in the adjacency matrix to 1 to
    // represent the edges in the graph
    adj[edge[0] - 1][edge[1] - 1] = 1;
    adj[edge[1] - 1][edge[0] - 1] = 1;
}
 
// Loop over all possible bitmasks
// of length N
for (let bitmask = 1; bitmask < (1 << N); bitmask++) {
    // Loop over all elements i
    // in the bitmask
    for (let i = 0; i < N; i++) {
        // Check if element i is used
        // in the bitmask
        if (1 & (bitmask >> i)) {
            // Loop over all other
            // elements j in the
            // bitmask
            for (let j = 0; j < N; j++) {
                // Check if element j
                // is adjacent to element
                // i in the graph, has a
                // different value in arr,
                // and is also used in
                // the bitmask
                if (j != i && arr[j] != arr[i] &&
                    (1 & (bitmask >> j)) && adj[arr[i] - 1][arr[j] - 1]) {
                    // update the count
                    // of permutations that
                    // end with element i
                    // and have the same set
                    // of used elements as
                    // the current bitmask
                    // by adding the count of
                    // permutations that end
                    // with element j and
                    // have the set of used
                    // elements represented
                    // by the bitmask with
                    // the ith bit flipped
                    // from 1 to 0
                    dp[i][bitmask] += dp[j][bitmask ^ (1 << i)];
                }
            }
        }
    }
}
 
// Sum up the counts of permutations
// that end with each element i and
// have used all N elements,
// represented by the bitmask with
// all N bits set to 1
let ans = 0;
for (let i = 0; i < N; i++) {
    ans += dp[i][(1 << N) - 1];
}
 
// Return the total count of required
// permutations
return ans;
}
 
// Driver's code
let N = 3, M = 2;
let arr = [1, 2, 3];
let graph = [[3, 1], [1, 2]];
 
// Call the countPermutations function
// with the given arguments and
// print the result
let ans = countPermutations(N, M, arr, graph);
console.log(ans);


Output

2

Time Complexity: O(N^2).
Auxiliary Space: O(N*2N).

Related Articles:



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads