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. There may be a lot of vertex covers possible for a graph.
Problem Find the size of the minimum size vertex cover, that is, cardinality of a vertex cover with minimum cardinality, for an undirected connected graph with V vertices and m edges.
Examples:
Input: V = 6, E = 6
6
/
/
1 -----5
/|\
3 | \
\ | \
2 4
Output: Minimum vertex cover size = 2
Consider subset of vertices {1, 2}, every edge
in above graph is either incident on vertex 1
or 2. Hence the minimum vertex cover = {1, 2},
the size of which is 2.
Input: V = 6, E = 7
2 ---- 4 ---- 6
/| |
1 | |
\| |
3 ---- 5
Output: Minimum vertex cover size = 3
Consider subset of vertices {2, 3, 4}, every
edge in above graph is either incident on
vertex 2, 3 or 4. Hence the minimum size of
a vertex cover can be 3.
Method 1 (Naive) We can check in O(E + V) time if a given subset of vertices is a vertex cover or not, using the following algorithm.
Generate all 2V subsets of vertices in graph and
do following for every subset.
1. edges_covered = 0
2. for each vertex in current subset
3. for all edges emerging out of current vertex
4. if the edge is not already marked visited
5. mark the edge visited
6. edges_covered++
7. if edges_covered is equal to total number edges
8. return size of current subset
An upper bound on time complexity of this solution is O((E + V) * 2V)
Method 2 (Binary Search) If we generate 2V subsets first by generating VCV subsets, then VC(V-1) subsets, and so on upto VC0 subsets(2V = VCV + VC(V-1) + … + VC1 + VC0). Our objective is now to find the minimum k such that at least one subset of size ‘k’ amongst VCk subsets is a vertex cover [ We know that if minimum size vertex cover is of size k, then there will exist a vertex cover of all sizes more than k. That is, there will be a vertex cover of size k + 1, k + 2, k + 3, …, n. ] Now let’s imagine a boolean array of size n and call it isCover[]. So if the answer of the question; “Does a vertex cover of size x exist?” is yes, we put a ‘1’ at xth position, otherwise ‘0’. The array isCover[] will look like:
The array is sorted and hence binary searchable, as no index before k will have a ‘1’, and every index after k(inclusive) will have a ‘1’, so k is the answer. So we can apply Binary Search to find the minimum size vertex set that covers all edges (this problem is equivalent to finding last 1 in isCover[]). Now the problem is how to generate all subsets of a given size. The idea is to use Gosper’s hack.
What is Gosper’s Hack? Gosper’s hack is a technique to get the next number with same number of bits set. So we set the first x bits from right and generate next number with x bits set until the number is less than 2V. In this way, we can generate all VCx numbers with x bits set.
CPP
int set = (1 << k) - 1;
int limit = (1 << V);
while (set < limit)
{
doStuff(set);
int c = set & -set;
int r = set + c;
set = (((r^set) >>> 2) / c) | r;
}
|
Javascript
let set = (1 << k) - 1;
let limit = (1 << V);
while (set < limit) {
doStuff(set);
let c = set & -set;
let r = set + c;
set = (((r^set) >>> 2) / c) | r;
}
|
Java
int set = ( 1 << k) - 1 ;
int limit = ( 1 << V);
while (set < limit) {
doStuff(set);
int c = set & -set;
int r = set + c;
set = (((r ^ set) >>> 2 ) / c) | r;
}
|
C#
int set = (1 << k) - 1;
int limit = (1 << V);
while ( set < limit) {
DoStuff( set );
int c = set & - set ;
int r = set + c;
set = (((r ^ set ) >>> 2) / c) | r;
}
|
Python
set = ( 1 << k) - 1
limit = ( 1 << V)
while set < limit:
DoStuff( set )
c = set & - set
r = set + c
set = (((r ^ set ) >> 2 ) / / c) | r
|
Source : StackExchange We use gosper’s hack to generate all subsets of size x(0 < x <= V), that is, to check whether we have a ‘1’ or ‘0’ at any index x in isCover[] array.
C++
#include<bits/stdc++.h>
#define maxn 25
using namespace std;
bool gr[maxn][maxn];
bool isCover( int V, int k, int E)
{
int set = (1 << k) - 1;
int limit = (1 << V);
bool vis[maxn][maxn];
while (set < limit)
{
memset (vis, 0, sizeof vis);
int cnt = 0;
for ( int j = 1, v = 1 ; j < limit ; j = j << 1, v++)
{
if (set & j)
{
for ( int k = 1 ; k <= V ; k++)
{
if (gr[v][k] && !vis[v][k])
{
vis[v][k] = 1;
vis[k][v] = 1;
cnt++;
}
}
}
}
if (cnt == E)
return true ;
int c = set & -set;
int r = set + c;
set = (((r^set) >> 2) / c) | r;
}
return false ;
}
int findMinCover( int n, int m)
{
int left = 1, right = n;
while (right > left)
{
int mid = (left + right) >> 1;
if (isCover(n, mid, m) == false )
left = mid + 1;
else
right = mid;
}
return left;
}
void insertEdge( int u, int v)
{
gr[u][v] = 1;
gr[v][u] = 1;
}
int main()
{
int V = 6, E = 6;
insertEdge(1, 2);
insertEdge(2, 3);
insertEdge(1, 3);
insertEdge(1, 4);
insertEdge(1, 5);
insertEdge(1, 6);
cout << "Minimum size of a vertex cover = "
<< findMinCover(V, E) << endl;
memset (gr, 0, sizeof gr);
V = 6, E = 7;
insertEdge(1, 2);
insertEdge(1, 3);
insertEdge(2, 3);
insertEdge(2, 4);
insertEdge(3, 5);
insertEdge(4, 5);
insertEdge(4, 6);
cout << "Minimum size of a vertex cover = "
<< findMinCover(V, E) << endl;
return 0;
}
|
Java
class GFG
{
static final int maxn = 25 ;
static boolean [][]gr = new boolean [maxn][maxn];
static boolean isCover( int V, int k, int E)
{
int set = ( 1 << k) - 1 ;
int limit = ( 1 << V);
boolean [][]vis = new boolean [maxn][maxn];;
while (set < limit)
{
for ( int i = 0 ; i < maxn; i++)
{
for ( int j = 0 ; j < maxn; j++)
{
vis[i][j] = false ;
}
}
int cnt = 0 ;
for ( int j = 1 , v = 1 ; j < limit ; j = j << 1 , v++)
{
if ((set & j) != 0 )
{
for ( int co = 1 ; co <= V ; co++)
{
if (gr[v][co] && !vis[v][co])
{
vis[v][co] = true ;
vis[co][v] = true ;
cnt++;
}
}
}
}
if (cnt == E)
return true ;
int co = set & -set;
int ro = set + co;
set = (((ro^set) >> 2 ) / co) | ro;
}
return false ;
}
static int findMinCover( int n, int m)
{
int left = 1 , right = n;
while (right > left)
{
int mid = (left + right) >> 1 ;
if (isCover(n, mid, m) == false )
left = mid + 1 ;
else
right = mid;
}
return left;
}
static void insertEdge( int u, int v)
{
gr[u][v] = true ;
gr[v][u] = true ;
}
public static void main(String[] args)
{
int V = 6 , E = 6 ;
insertEdge( 1 , 2 );
insertEdge( 2 , 3 );
insertEdge( 1 , 3 );
insertEdge( 1 , 4 );
insertEdge( 1 , 5 );
insertEdge( 1 , 6 );
System.out.print( "Minimum size of a vertex cover = "
+ findMinCover(V, E) + "\n" );
for ( int i = 0 ; i < maxn; i++)
{
for ( int j = 0 ; j < maxn; j++)
{
gr[i][j] = false ;
}
}
V = 6 ;
E = 7 ;
insertEdge( 1 , 2 );
insertEdge( 1 , 3 );
insertEdge( 2 , 3 );
insertEdge( 2 , 4 );
insertEdge( 3 , 5 );
insertEdge( 4 , 5 );
insertEdge( 4 , 6 );
System.out.print( "Minimum size of a vertex cover = "
+ findMinCover(V, E) + "\n" );
}
}
|
Python3
def isCover(V, k, E):
Set = ( 1 << k) - 1
limit = ( 1 << V)
vis = [[ None ] * maxn for i in range (maxn)]
while ( Set < limit):
vis = [[ 0 ] * maxn for i in range (maxn)]
cnt = 0
j = 1
v = 1
while (j < limit):
if ( Set & j):
for k in range ( 1 , V + 1 ):
if (gr[v][k] and not vis[v][k]):
vis[v][k] = 1
vis[k][v] = 1
cnt + = 1
j = j << 1
v + = 1
if (cnt = = E):
return True
c = Set & - Set
r = Set + c
Set = (((r ^ Set ) >> 2 ) / / c) | r
return False
def findMinCover(n, m):
left = 1
right = n
while (right > left):
mid = (left + right) >> 1
if (isCover(n, mid, m) = = False ):
left = mid + 1
else :
right = mid
return left
def insertEdge(u, v):
gr[u][v] = 1
gr[v][u] = 1
maxn = 25
gr = [[ None ] * maxn for i in range (maxn)]
V = 6
E = 6
insertEdge( 1 , 2 )
insertEdge( 2 , 3 )
insertEdge( 1 , 3 )
insertEdge( 1 , 4 )
insertEdge( 1 , 5 )
insertEdge( 1 , 6 )
print ( "Minimum size of a vertex cover = " ,
findMinCover(V, E))
gr = [[ 0 ] * maxn for i in range (maxn)]
V = 6
E = 7
insertEdge( 1 , 2 )
insertEdge( 1 , 3 )
insertEdge( 2 , 3 )
insertEdge( 2 , 4 )
insertEdge( 3 , 5 )
insertEdge( 4 , 5 )
insertEdge( 4 , 6 )
print ( "Minimum size of a vertex cover = " ,
findMinCover(V, E))
|
Javascript
const maxn = 25;
const gr = Array.from({ length: maxn }, () => new Array(maxn).fill( false ));
function isCover(V, k, E) {
let set = (1 << k) - 1;
const limit = 1 << V;
const vis = Array.from({ length: maxn }, () => new Array(maxn).fill( false ));
while (set < limit) {
for (let i = 0; i < maxn; i++) {
for (let j = 0; j < maxn; j++) {
vis[i][j] = false ;
}
}
let cnt = 0;
for (let j = 1, v = 1 ; j < limit ; j = j << 1, v++) {
if ((set & j) !== 0) {
for (let co = 1 ; co <= V ; co++) {
if (gr[v][co] && !vis[v][co]) {
vis[v][co] = true ;
vis[co][v] = true ;
cnt++;
}
}
}
}
if (cnt === E) {
return true ;
}
const cO = set & -set;
const rO = set + cO;
set = (((rO^set) >> 2) / cO) | rO;
}
return false ;
}
function findMinCover(n, m) {
let left = 1;
let right = n;
while (right > left) {
let mid = (left + right) >> 1;
if (isCover(n, mid, m) === false ) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
function insertEdge(u, v) {
gr[u][v] = true ;
gr[v][u] = true ;
}
let V = 6, E = 6;
insertEdge(1, 2);
insertEdge(2, 3);
insertEdge(1, 3);
insertEdge(1, 4);
insertEdge(1, 5);
insertEdge(1, 6);
console.log( "Minimum size of a vertex cover = " + findMinCover(V, E) + "\n" );
for (let i = 0; i < maxn; i++) {
for (let j = 0; j < maxn; j++) {
gr[i][j] = false ;
}
}
V = 6;
E = 7;
insertEdge(1, 2);
insertEdge(1, 3);
insertEdge(2, 3);
insertEdge(2, 4);
insertEdge(3, 5);
insertEdge(4, 5);
insertEdge(4, 6);
console.log( "Minimum size of a vertex cover = " + findMinCover(V, E) + "\n" );
|
C#
using System;
class GFG
{
static readonly int maxn = 25;
static bool [,]gr = new bool [maxn, maxn];
static bool isCover( int V, int k, int E)
{
int set = (1 << k) - 1;
int limit = (1 << V);
bool [,]vis = new bool [maxn, maxn];;
while ( set < limit)
{
for ( int i = 0; i < maxn; i++)
{
for ( int j = 0; j < maxn; j++)
{
vis[i, j] = false ;
}
}
int cnt = 0;
for ( int j = 1, v = 1 ; j < limit ; j = j << 1, v++)
{
if (( set & j) != 0)
{
for ( int co = 1 ; co <= V ; co++)
{
if (gr[v, co] && !vis[v, co])
{
vis[v, co] = true ;
vis[co, v] = true ;
cnt++;
}
}
}
}
if (cnt == E)
return true ;
int cO = set & - set ;
int rO = set + cO;
set = (((rO^ set ) >> 2) / cO) | rO;
}
return false ;
}
static int findMinCover( int n, int m)
{
int left = 1, right = n;
while (right > left)
{
int mid = (left + right) >> 1;
if (isCover(n, mid, m) == false )
left = mid + 1;
else
right = mid;
}
return left;
}
static void insertEdge( int u, int v)
{
gr[u, v] = true ;
gr[v, u] = true ;
}
public static void Main(String[] args)
{
int V = 6, E = 6;
insertEdge(1, 2);
insertEdge(2, 3);
insertEdge(1, 3);
insertEdge(1, 4);
insertEdge(1, 5);
insertEdge(1, 6);
Console.Write( "Minimum size of a vertex cover = "
+ findMinCover(V, E) + "\n" );
for ( int i = 0; i < maxn; i++)
{
for ( int j = 0; j < maxn; j++)
{
gr[i,j] = false ;
}
}
V = 6;
E = 7;
insertEdge(1, 2);
insertEdge(1, 3);
insertEdge(2, 3);
insertEdge(2, 4);
insertEdge(3, 5);
insertEdge(4, 5);
insertEdge(4, 6);
Console.Write( "Minimum size of a vertex cover = "
+ findMinCover(V, E) + "\n" );
}
}
|
OutputMinimum size of a vertex cover = 2
Minimum size of a vertex cover = 3
Conclusion:
Time Complexity : O (E * ( VCV/2 + VCV/4 + VCV/8 +…upto VCk ) ) These terms are not more than log(V) in worst case.
Auxiliary Space Complexity : O(V^2)
Note: Gosper’s hack works for upto V = 31 only, if we take ‘long long int’ instead of ‘int’ it can work upto V = 63. This article is contributed by Saumye Malhotra .
If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.