Find the minimum dominating set of a Binary tree

09 Oct, 2021
Given a binary tree with N nodes numbered [1, N], the task is to find the size of the smallest Dominating set of that tree.
A set of nodes is said to be a dominating node if every node in the binary tree not present in the set is an immediate child/parent to any node in that set.
Examples:
Input: 
                     1
                    /
                   2
                  / \
                 4   3
               /
              5
            /  \
           6    7
          / \    \
         8   9   10
Output:  3
Explanation: 
Smallest dominating set is {2, 6, 7}

Input: 
                     1
                   /   \
                  2     3
                 / \   / \
                4   5 6   7
               / \   /
              8  9  10
Output:  4
Explanation: 
One of the smallest
dominating set = {2, 3, 6, 4}
Approach: In order to solve this problem we are using a dynamic programming approach by defining the following two states for every node:
The first state compulsory tells us whether it is compulsory to choose the node in the set or not.
The second state covered, tells us whether the node’s parent/child is in the set or not.
If it is compulsory to choose the node, we choose it and mark its children as covered. Otherwise, we have an option to choose it or reject it and then update its children as covered or not accordingly. Check the states for every node and find the required size of the set accordingly.Below code is the implementation of the above approach:
C++
Java
Python3
C#
Javascript
/* C++ program to find the size of theminimum dominating set of the tree */ #include <bits/stdc++.h>using namespace std; #define N 1005 // Definition of a tree nodestruct Node {    int data;    Node *left, *right;}; /* Helper function that allocates anew node */Node* newNode(int data){    Node* node = new Node();    node->data = data;    node->left = node->right = NULL;    return node;} // DP array to precompute// and store the resultsint dp[N][5][5]; // minDominatingSettion to return the size of// the minimum dominating set of the arrayint minDominatingSet(Node* root, int covered,                     int compulsory){    // Base case    if (!root)        return 0;     // Setting the compulsory value if needed    if (!root->left and !root->right and !covered)        compulsory = true;     // Check if the answer is already computed    if (dp[root->data][covered][compulsory] != -1)        return dp[root->data][covered][compulsory];     // If it is compulsory to select    // the node    if (compulsory) {        // Choose the node and set its children as covered        return dp[root->data]                 [covered]                 [compulsory]               = 1                 + minDominatingSet(                       root->left, 1, 0)                 + minDominatingSet(                       root->right, 1, 0);    }     // If it is covered    if (covered) {        return dp[root->data]                 [covered]                 [compulsory]               = min(                   1                       + minDominatingSet(                             root->left, 1, 0)                       + minDominatingSet(                             root->right, 1, 0),                   minDominatingSet(                       root->left, 0, 0)                       + minDominatingSet(                             root->right, 0, 0));    }     // If the current node is neither covered nor    // needs to be selected compulsorily    int ans = 1              + minDominatingSet(                    root->left, 1, 0)              + minDominatingSet(                    root->right, 1, 0);     if (root->left) {        ans = min(ans,                  minDominatingSet(                      root->left, 0, 1)                      + minDominatingSet(                            root->right, 0, 0));    }    if (root->right) {        ans = min(ans,                  minDominatingSet(                      root->left, 0, 0)                      + minDominatingSet(                            root->right, 0, 1));    }     // Store the result    return dp[root->data]             [covered]             [compulsory]           = ans;} // Driver codesigned main(){    // initialising the DP array    memset(dp, -1, sizeof(dp));     // Constructing the tree    Node* root = newNode(1);    root->left = newNode(2);    root->left->left = newNode(3);    root->left->right = newNode(4);    root->left->left->left = newNode(5);    root->left->left->left->left = newNode(6);    root->left->left->left->right = newNode(7);    root->left->left->left->right->right = newNode(10);    root->left->left->left->left->left = newNode(8);    root->left->left->left->left->right = newNode(9);     cout << minDominatingSet(root, 0, 0) << endl;     return 0;}
// Java program to find the size of the//minimum dominating set of the treeimport java.util.*; class GFG{ static final int N = 1005; // Definition of a tree nodestatic class Node{    int data;    Node left, right;}; // Helper function that allocates a// new nodestatic Node newNode(int data){    Node node = new Node();    node.data = data;    node.left = node.right = null;    return node;} // DP array to precompute// and store the resultsstatic int [][][]dp = new int[N][5][5]; // minDominatingSettion to return the size of// the minimum dominating set of the arraystatic int minDominatingSet(Node root,                            int covered,                            int compulsory){    // Base case    if (root == null)        return 0;         // Setting the compulsory value if needed    if (root.left != null &&       root.right != null &&       covered > 0)        compulsory = 1;     // Check if the answer is already computed    if (dp[root.data][covered][compulsory] != -1)        return dp[root.data][covered][compulsory];     // If it is compulsory to select    // the node    if (compulsory > 0)    {                 // Choose the node and set its        // children as covered        return dp[root.data][covered][compulsory] = 1 +                 minDominatingSet(root.left, 1, 0) +                 minDominatingSet(root.right, 1, 0);    }     // If it is covered    if (covered > 0)    {        return dp[root.data][covered]                 [compulsory] = Math.min(1 +                  minDominatingSet(root.left, 1, 0) +                  minDominatingSet(root.right, 1, 0),                  minDominatingSet(root.left, 0, 0)+                  minDominatingSet(root.right, 0, 0));    }     // If the current node is neither covered nor    // needs to be selected compulsorily    int ans = 1 + minDominatingSet(root.left, 1, 0) +                  minDominatingSet(root.right, 1, 0);     if (root.left != null)    {        ans = Math.min(ans,              minDominatingSet(root.left, 0, 1) +              minDominatingSet(root.right, 0, 0));    }    if (root.right != null)    {        ans = Math.min(ans,              minDominatingSet(root.left, 0, 0) +              minDominatingSet(root.right, 0, 1));    }     // Store the result    return dp[root.data][covered][compulsory] = ans;} // Driver codepublic static void main(String[] args){         // Initialising the DP array    for(int i = 0; i < N; i++)    {        for(int j = 0; j < 5; j++)        {            for(int l = 0; l < 5; l++)                dp[i][j][l] = -1;        }    }     // Constructing the tree    Node root = newNode(1);    root.left = newNode(2);    root.left.left = newNode(3);    root.left.right = newNode(4);    root.left.left.left = newNode(5);    root.left.left.left.left = newNode(6);    root.left.left.left.right = newNode(7);    root.left.left.left.right.right = newNode(10);    root.left.left.left.left.left = newNode(8);    root.left.left.left.left.right = newNode(9);     System.out.print(minDominatingSet(        root, 0, 0) + "\n");}} // This code is contributed by amal kumar choubey
# Python3 program to find the size of the# minimum dominating set of the tree */N = 1005  # Definition of a tree nodeclass Node:         def __init__(self, data):                 self.data = data        self.left = None        self.right = None      # Helper function that allocates a# new nodedef newNode(data):     node = Node(data)    return node  # DP array to precompute# and store the resultsdp = [[[-1 for i in range(5)] for j in range(5)] for k in range(N)];  # minDominatingSettion to return the size of# the minimum dominating set of the arraydef minDominatingSet(root, covered, compulsory):     # Base case    if (not root):        return 0;      # Setting the compulsory value if needed    if (not root.left and not root.right and not covered):        compulsory = True;      # Check if the answer is already computed    if (dp[root.data][covered][compulsory] != -1):        return dp[root.data][covered][compulsory];      # If it is compulsory to select    # the node    if (compulsory):                 dp[root.data][covered][compulsory] = 1 + minDominatingSet(root.left, 1, 0) + minDominatingSet(root.right, 1, 0);                 # Choose the node and set its children as covered        return dp[root.data][covered][compulsory]          # If it is covered    if (covered):        dp[root.data][covered][compulsory] = min(1 + minDominatingSet(root.left, 1, 0) + minDominatingSet(root.right, 1, 0),minDominatingSet(root.left, 0, 0)+ minDominatingSet(root.right, 0, 0));        return dp[root.data][covered][compulsory]          # If the current node is neither covered nor    # needs to be selected compulsorily    ans = 1 + minDominatingSet(root.left, 1, 0) + minDominatingSet(root.right, 1, 0);      if (root.left):        ans = min(ans, minDominatingSet(root.left, 0, 1) + minDominatingSet(root.right, 0, 0));         if (root.right):        ans = min(ans, minDominatingSet( root.left, 0, 0) + minDominatingSet(root.right, 0, 1));          # Store the result    dp[root.data][covered][compulsory]= ans;    return ans # Driver codeif __name__=='__main__':          # Constructing the tree    root = newNode(1);    root.left = newNode(2);    root.left.left = newNode(3);    root.left.right = newNode(4);    root.left.left.left = newNode(5);    root.left.left.left.left = newNode(6);    root.left.left.left.right = newNode(7);    root.left.left.left.right.right = newNode(10);    root.left.left.left.left.left = newNode(8);    root.left.left.left.left.right = newNode(9);      print(minDominatingSet(root, 0, 0))     # This code is contributed by rutvik_56
// C# program to find the size of the//minimum dominating set of the treeusing System;class GFG{ static readonly int N = 1005; // Definition of a tree nodepublic class Node{    public int data;    public Node left, right;}; // Helper function that allocates a// new nodepublic static Node newNode(int data){    Node node = new Node();    node.data = data;    node.left = node.right = null;    return node;} // DP array to precompute// and store the resultsstatic int [,,]dp = new int[N, 5, 5]; // minDominatingSettion to return the size of// the minimum dominating set of the arraystatic int minDominatingSet(Node root,                            int covered,                            int compulsory){    // Base case    if (root == null)        return 0;         // Setting the compulsory value if needed    if (root.left != null &&       root.right != null &&       covered > 0)        compulsory = 1;     // Check if the answer is already computed    if (dp[root.data, covered, compulsory] != -1)        return dp[root.data, covered, compulsory];     // If it is compulsory to select    // the node    if (compulsory > 0)    {                 // Choose the node and set its        // children as covered        return dp[root.data, covered, compulsory] = 1 +                    minDominatingSet(root.left, 1, 0) +                   minDominatingSet(root.right, 1, 0);    }     // If it is covered    if (covered > 0)    {        return dp[root.data, covered, compulsory] = Math.Min(1 +                             minDominatingSet(root.left, 1, 0) +                             minDominatingSet(root.right, 1, 0),                             minDominatingSet(root.left, 0, 0)+                            minDominatingSet(root.right, 0, 0));    }     // If the current node is neither covered nor    // needs to be selected compulsorily    int ans = 1 + minDominatingSet(root.left, 1, 0) +                  minDominatingSet(root.right, 1, 0);     if (root.left != null)    {        ans = Math.Min(ans,              minDominatingSet(root.left, 0, 1) +              minDominatingSet(root.right, 0, 0));    }    if (root.right != null)    {        ans = Math.Min(ans,              minDominatingSet(root.left, 0, 0) +              minDominatingSet(root.right, 0, 1));    }     // Store the result    return dp[root.data, covered, compulsory] = ans;} // Driver codepublic static void Main(String[] args){         // Initialising the DP array    for(int i = 0; i < N; i++)    {        for(int j = 0; j < 5; j++)        {            for(int l = 0; l < 5; l++)                dp[i, j, l] = -1;        }    }     // Constructing the tree    Node root = newNode(1);    root.left = newNode(2);    root.left.left = newNode(3);    root.left.right = newNode(4);    root.left.left.left = newNode(5);    root.left.left.left.left = newNode(6);    root.left.left.left.right = newNode(7);    root.left.left.left.right.right = newNode(10);    root.left.left.left.left.left = newNode(8);    root.left.left.left.left.right = newNode(9);     Console.Write(minDominatingSet                  root, 0, 0) + "\n");}} // This code is contributed by Rohit_ranjan
<script>     // JavaScript program to find the size of the    //minimum dominating set of the tree         let N = 1005;      // Definition of a tree node    class Node    {       constructor(data) {           this.left = null;           this.right = null;           this.data = data;        }    }         // Helper function that allocates a    // new node    function newNode(data)    {        let node = new Node(data);        return node;    }     // DP array to precompute    // and store the results    let dp = new Array(N);     // minDominatingSettion to return the size of    // the minimum dominating set of the array    function minDominatingSet(root, covered, compulsory)    {        // Base case        if (root == null)            return 0;         // Setting the compulsory value if needed        if (root.left != null &&           root.right != null &&           covered > 0)            compulsory = 1;         // Check if the answer is already computed        if (dp[root.data][covered][compulsory] != -1)            return dp[root.data][covered][compulsory];         // If it is compulsory to select        // the node        if (compulsory > 0)        {             // Choose the node and set its            // children as covered            return dp[root.data][covered][compulsory] = 1 +                     minDominatingSet(root.left, 1, 0) +                     minDominatingSet(root.right, 1, 0);        }         // If it is covered        if (covered > 0)        {            return dp[root.data][covered]                     [compulsory] = Math.min(1 +                      minDominatingSet(root.left, 1, 0) +                      minDominatingSet(root.right, 1, 0),                      minDominatingSet(root.left, 0, 0)+                      minDominatingSet(root.right, 0, 0));        }         // If the current node is neither covered nor        // needs to be selected compulsorily        let ans = 1 + minDominatingSet(root.left, 1, 0) +                      minDominatingSet(root.right, 1, 0);         if (root.left != null)        {            ans = Math.min(ans,                  minDominatingSet(root.left, 0, 1) +                  minDominatingSet(root.right, 0, 0));        }        if (root.right != null)        {            ans = Math.min(ans,                  minDominatingSet(root.left, 0, 0) +                  minDominatingSet(root.right, 0, 1));        }         // Store the result        dp[root.data][covered][compulsory] = ans;        return dp[root.data][covered][compulsory];    }         // Initialising the DP array    for(let i = 0; i < N; i++)    {        dp[i] = new Array(5);        for(let j = 0; j < 5; j++)        {            dp[i][j] = new Array(5);            for(let l = 0; l < 5; l++)                dp[i][j][l] = -1;        }    }      // Constructing the tree    let root = newNode(1);    root.left = newNode(2);    root.left.left = newNode(3);    root.left.right = newNode(4);    root.left.left.left = newNode(5);    root.left.left.left.left = newNode(6);    root.left.left.left.right = newNode(7);    root.left.left.left.right.right = newNode(10);    root.left.left.left.left.left = newNode(8);    root.left.left.left.left.right = newNode(9);      document.write(minDominatingSet(root, 0, 0));             </script>
3
 
Time Complexity: O(N) Auxiliary Space: O(N) 
Amal Kumar Choubey
Rohit_ranjan
rutvik_56
rameshtravel07
pankajsharmagfg
ashutoshsinghgeeksforgeeks
Competitive Programming
Data Structures
Dynamic Programming
Recursion
Tree
Data Structures
Dynamic Programming
Recursion
Tree
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.