Vertex Cover Problem | Set 2 (Dynamic Programming Solution for Tree)

A vertex cover of an undirected graph is a subset of its vertices such that for every edge (u, v) of the graph, either ‘u’ or ‘v’ is in vertex cover. Although the name is Vertex Cover, the set covers all edges of the given graph.
The problem to find minimum size vertex cover of a graph is NP complete. But it can be solved in polynomial time for trees. In this post a solution for Binary Tree is discussed. The same solution can be extended for n-ary trees.

For example, consider the following binary tree. The smallest vertex cover is {20, 50, 30} and size of the vertex cover is 3.
LargestIndependentSet1

The idea is to consider following two possibilities for root and recursively for all nodes down the root.
1) Root is part of vertex cover: In this case root covers all children edges. We recursively calculate size of vertex covers for left and right subtrees and add 1 to the result (for root).

2) Root is not part of vertex cover: In this case, both children of root must be included in vertex cover to cover all root to children edges. We recursively calculate size of vertex covers of all grandchildren and number of children to the result (for two children of root).

Below are implementation of above idea.

C



filter_none

edit
close

play_arrow

link
brightness_4
code

// A naive recursive C implementation for vertex cover problem for a tree
#include <stdio.h>
#include <stdlib.h>
  
// A utility function to find min of two integers
int min(int x, int y) { return (x < y)? x: y; }
  
/* A binary tree node has data, pointer to left child and a pointer to
   right child */
struct node
{
    int data;
    struct node *left, *right;
};
  
// The function returns size of the minimum vertex cover
int vCover(struct node *root)
{
    // The size of minimum vertex cover is zero if tree is empty or there
    // is only one node
    if (root == NULL)
        return 0;
    if (root->left == NULL && root->right == NULL)
        return 0;
  
    // Calculate size of vertex cover when root is part of it
    int size_incl = 1 + vCover(root->left) + vCover(root->right);
  
    // Calculate size of vertex cover when root is not part of it
    int size_excl = 0;
    if (root->left)
      size_excl += 1 + vCover(root->left->left) + vCover(root->left->right);
    if (root->right)
      size_excl += 1 + vCover(root->right->left) + vCover(root->right->right);
  
    // Return the minimum of two sizes
    return min(size_incl, size_excl);
}
  
// A utility function to create a node
struct node* newNode( int data )
{
    struct node* temp = (struct node *) malloc( sizeof(struct node) );
    temp->data = data;
    temp->left = temp->right = NULL;
    return temp;
}
  
// Driver program to test above functions
int main()
{
    // Let us construct the tree given in the above diagram
    struct node *root         = newNode(20);
    root->left                = newNode(8);
    root->left->left          = newNode(4);
    root->left->right         = newNode(12);
    root->left->right->left   = newNode(10);
    root->left->right->right  = newNode(14);
    root->right               = newNode(22);
    root->right->right        = newNode(25);
  
    printf ("Size of the smallest vertex cover is %d ", vCover(root));
  
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// A naive recursive Java implementation 
// for vertex cover problem for a tree
  
class GFG
{
    // A utility function to find min of two integers
    static int min(int x, int y)
    {
        return (x < y) ? x : y;
    }
  
    /*
    * A binary tree node has data, pointer
    to left child and a pointer to right
    * child
    */
    static class node 
    {
        int data;
        node left, right;
    };
  
    // The function returns size 
    // of the minimum vertex cover
    static int vCover(node root) 
    {
        // The size of minimum vertex cover
        // is zero if tree is empty or there
        // is only one node
        if (root == null)
            return 0;
        if (root.left == null && root.right == null)
            return 0;
  
        // Calculate size of vertex cover
        // when root is part of it
        int size_incl = 1 + vCover(root.left) + 
                               vCover(root.right);
  
        // Calculate size of vertex cover
        // when root is not part of it
        int size_excl = 0;
        if (root.left != null)
            size_excl += 1 + vCover(root.left.left) + 
                              vCover(root.left.right);
        if (root.right != null)
            size_excl += 1 + vCover(root.right.left) + 
                                vCover(root.right.right);
  
        // Return the minimum of two sizes
        return Math.min(size_incl, size_excl);
    }
  
    // A utility function to create a node
    static node newNode(int data) 
    {
        node temp = new node();
        temp.data = data;
        temp.left = temp.right = null;
        return temp;
    }
  
    // Driver code
    public static void main(String[] args) 
    {
        // Let us conthe tree given in the above diagram
        node root = newNode(20);
        root.left = newNode(8);
        root.left.left = newNode(4);
        root.left.right = newNode(12);
        root.left.right.left = newNode(10);
        root.left.right.right = newNode(14);
        root.right = newNode(22);
        root.right.right = newNode(25);
  
        System.out.printf("Size of the smallest vertex"
                            "cover is %d ", vCover(root));
  
    }
}
  
// This code is contributed by 29AjayKumar

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// A naive recursive C# implementation 
// for vertex cover problem for a tree
using System;
  
class GFG
{
    // A utility function to find 
    // min of two integers
    static int min(int x, int y)
    {
        return (x < y) ? x : y;
    }
  
    /*
    * A binary tree node has data, pointer
    to left child and a pointer to right
    * child
    */
    public class node 
    {
        public int data;
        public node left, right;
    };
  
    // The function returns size 
    // of the minimum vertex cover
    static int vCover(node root) 
    {
        // The size of minimum vertex cover
        // is zero if tree is empty or there
        // is only one node
        if (root == null)
            return 0;
        if (root.left == null && 
            root.right == null)
            return 0;
  
        // Calculate size of vertex cover
        // when root is part of it
        int size_incl = 1 + vCover(root.left) + 
                            vCover(root.right);
  
        // Calculate size of vertex cover
        // when root is not part of it
        int size_excl = 0;
        if (root.left != null)
            size_excl += 1 + vCover(root.left.left) + 
                             vCover(root.left.right);
        if (root.right != null)
            size_excl += 1 + vCover(root.right.left) + 
                             vCover(root.right.right);
  
        // Return the minimum of two sizes
        return Math.Min(size_incl, size_excl);
    }
  
    // A utility function to create a node
    static node newNode(int data) 
    {
        node temp = new node();
        temp.data = data;
        temp.left = temp.right = null;
        return temp;
    }
  
    // Driver code
    public static void Main(String[] args) 
    {
        // Let us conthe tree given 
        // in the above diagram
        node root = newNode(20);
        root.left = newNode(8);
        root.left.left = newNode(4);
        root.left.right = newNode(12);
        root.left.right.left = newNode(10);
        root.left.right.right = newNode(14);
        root.right = newNode(22);
        root.right.right = newNode(25);
  
        Console.Write("Size of the smallest vertex"
                      "cover is {0} ", vCover(root));
    }
}
  
// This code is contributed by 29AjayKumar

chevron_right


Output:

Size of the smallest vertex cover is 3

Time complexity of the above naive recursive approach is exponential. It should be noted that the above function computes the same subproblems again and again. For example, vCover of node with value 50 is evaluated twice as 50 is grandchild of 10 and child of 20.
Since same suproblems are called again, this problem has Overlapping Subprolems property. So Vertex Cover problem has both properties (see this and this) of a dynamic programming problem. Like other typical Dynamic Programming(DP) problems, re-computations of same subproblems can be avoided by storing the solutions to subproblems and solving problems in bottom up manner.

Following is the implementation of Dynamic Programming based solution. In the following solution, an additional field ‘vc’ is added to tree nodes. The initial value of ‘vc’ is set as 0 for all nodes. The recursive function vCover() calculates ‘vc’ for a node only if it is not already set.

C

filter_none

edit
close

play_arrow

link
brightness_4
code

/* Dynamic programming based program for Vertex Cover problem for 
   a Binary Tree */
#include <stdio.h>
#include <stdlib.h>
  
// A utility function to find min of two integers
int min(int x, int y) { return (x < y)? x: y; }
  
/* A binary tree node has data, pointer to left child and a pointer to
   right child */
struct node
{
    int data;
    int vc;
    struct node *left, *right;
};
  
// A memoization based function that returns size of the minimum vertex cover.
int vCover(struct node *root)
{
    // The size of minimum vertex cover is zero if tree is empty or there
    // is only one node
    if (root == NULL)
        return 0;
    if (root->left == NULL && root->right == NULL)
        return 0;
  
    // If vertex cover for this node is already evaluated, then return it
    // to save recomputation of same subproblem again.
    if (root->vc != 0)
        return root->vc;
  
    // Calculate size of vertex cover when root is part of it
    int size_incl = 1 + vCover(root->left) + vCover(root->right);
  
    // Calculate size of vertex cover when root is not part of it
    int size_excl = 0;
    if (root->left)
      size_excl += 1 + vCover(root->left->left) + vCover(root->left->right);
    if (root->right)
      size_excl += 1 + vCover(root->right->left) + vCover(root->right->right);
  
    // Minimum of two values is vertex cover, store it before returning
    root->vc =  min(size_incl, size_excl);
  
    return root->vc;
}
  
// A utility function to create a node
struct node* newNode( int data )
{
    struct node* temp = (struct node *) malloc( sizeof(struct node) );
    temp->data = data;
    temp->left = temp->right = NULL;
    temp->vc = 0; // Set the vertex cover as 0
    return temp;
}
  
// Driver program to test above functions
int main()
{
    // Let us construct the tree given in the above diagram
    struct node *root         = newNode(20);
    root->left                = newNode(8);
    root->left->left          = newNode(4);
    root->left->right         = newNode(12);
    root->left->right->left   = newNode(10);
    root->left->right->right  = newNode(14);
    root->right               = newNode(22);
    root->right->right        = newNode(25);
  
    printf ("Size of the smallest vertex cover is %d ", vCover(root));
  
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

/* Dynamic programming based program for 
Vertex Cover problem for a Binary Tree */
  
class GFG
{
    // A utility function to find min of two integers
    static int min(int x, int y)
    {
        return (x < y) ? x : y;
    }
  
    /*
    * A binary tree node has data, pointer 
    to left child and a pointer to right
    * child
    */
    static class node 
    {
        int data;
        int vc;
        node left, right;
    };
  
    // A memoization based function that returns
    // size of the minimum vertex cover.
    static int vCover(node root)
    {
        // The size of minimum vertex cover is zero
        //  if tree is empty or there is only one node
        if (root == null)
            return 0;
        if (root.left == null && root.right == null)
            return 0;
  
        // If vertex cover for this node is 
        // already evaluated, then return it
        // to save recomputation of same subproblem again.
        if (root.vc != 0)
            return root.vc;
  
        // Calculate size of vertex cover 
        // when root is part of it
        int size_incl = 1 + vCover(root.left) + 
                            vCover(root.right);
  
        // Calculate size of vertex cover
        // when root is not part of it
        int size_excl = 0;
        if (root.left != null)
            size_excl += 1 + vCover(root.left.left) + 
                                vCover(root.left.right);
        if (root.right != null)
            size_excl += 1 + vCover(root.right.left) +
                                vCover(root.right.right);
  
        // Minimum of two values is vertex cover, 
        // store it before returning
        root.vc = Math.min(size_incl, size_excl);
  
        return root.vc;
    }
  
    // A utility function to create a node
    static node newNode(int data)
    {
        node temp = new node();
        temp.data = data;
        temp.left = temp.right = null;
        temp.vc = 0; // Set the vertex cover as 0
        return temp;
    }
  
    // Driver code
    public static void main(String[] args)
    {
        // Let us conthe tree given in the above diagram
        node root = newNode(20);
        root.left = newNode(8);
        root.left.left = newNode(4);
        root.left.right = newNode(12);
        root.left.right.left = newNode(10);
        root.left.right.right = newNode(14);
        root.right = newNode(22);
        root.right.right = newNode(25);
  
        System.out.printf("Size of the smallest vertex"
                            "cover is %d ", vCover(root));
    }
}
  
// This code is contributed by PrinciRaj1992

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

/* Dynamic programming based program for 
Vertex Cover problem for a Binary Tree */
using System;
  
class GFG
{
    // A utility function to find 
    // min of two integers
    static int min(int x, int y)
    {
        return (x < y) ? x : y;
    }
  
    /*
    * A binary tree node has data, pointer 
    to left child and a pointer to right
    * child
    */
    class node 
    {
        public int data;
        public int vc;
        public node left, right;
    };
  
    // A memoization based function that returns
    // size of the minimum vertex cover.
    static int vCover(node root)
    {
        // The size of minimum vertex cover is zero
        // if tree is empty or there is only one node
        if (root == null)
            return 0;
        if (root.left == null && 
            root.right == null)
            return 0;
  
        // If vertex cover for this node is 
        // already evaluated, then return it
        // to save recomputation of same subproblem again.
        if (root.vc != 0)
            return root.vc;
  
        // Calculate size of vertex cover 
        // when root is part of it
        int size_incl = 1 + vCover(root.left) + 
                            vCover(root.right);
  
        // Calculate size of vertex cover
        // when root is not part of it
        int size_excl = 0;
        if (root.left != null)
            size_excl += 1 + vCover(root.left.left) + 
                             vCover(root.left.right);
        if (root.right != null)
            size_excl += 1 + vCover(root.right.left) +
                             vCover(root.right.right);
  
        // Minimum of two values is vertex cover, 
        // store it before returning
        root.vc = Math.Min(size_incl, size_excl);
  
        return root.vc;
    }
  
    // A utility function to create a node
    static node newNode(int data)
    {
        node temp = new node();
        temp.data = data;
        temp.left = temp.right = null;
        temp.vc = 0; // Set the vertex cover as 0
        return temp;
    }
  
    // Driver code
    public static void Main(String[] args)
    {
        // Let us conthe tree given in the above diagram
        node root = newNode(20);
        root.left = newNode(8);
        root.left.left = newNode(4);
        root.left.right = newNode(12);
        root.left.right.left = newNode(10);
        root.left.right.right = newNode(14);
        root.right = newNode(22);
        root.right.right = newNode(25);
  
        Console.Write("Size of the smallest vertex"
                      "cover is {0} ", vCover(root));
    }
}
  
// This code is contributed by PrinciRaj1992

chevron_right


Output:

Size of the smallest vertex cover is 3

References:
http://courses.csail.mit.edu/6.006/spring11/lectures/lec21.pdf

Exercise:
Extend the above solution for n-ary trees.

This article is contributed by Udit Gupta. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up

Improved By : princiraj1992, 29AjayKumar

Article Tags :
Practice Tags :


18


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.