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.

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 is C implementation of above idea.

`// 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; ` `} ` |

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 C 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.

`/* 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; ` `} ` |

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

## Recommended Posts:

- Vertex Cover Problem | Set 1 (Introduction and Approximate Algorithm)
- Compute nCr % p | Set 1 (Introduction and Dynamic Programming Solution)
- How to solve a Dynamic Programming Problem ?
- Proof that vertex cover is NP complete
- Understanding The Coin Change Problem With Dynamic Programming
- Travelling Salesman Problem | Set 1 (Naive and Dynamic Programming)
- Dynamic Programming | High-effort vs. Low-effort Tasks Problem
- Exact Cover Problem and Algorithm X | Set 1
- Exact Cover Problem and Algorithm X | Set 2 (Implementation with DLX)
- Set Cover Problem | Set 1 (Greedy Approximate Algorithm)
- A Space Optimized DP solution for 0-1 Knapsack Problem
- Word Wrap problem ( Space optimized solution )
- Dynamic Programming on Trees | Set 2
- Bitmasking and Dynamic Programming | Set-2 (TSP)
- Dynamic Programming on Trees | Set-1