Open In App

Finding minimum vertex cover size of a graph using binary search

Improve
Improve
Like Article
Like
Save
Share
Report

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:

1 2 3 . . . k . . . n
0 0 0 . . . 1 . . . 1

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)
{
    // Do your stuff with current set
    doStuff(set);
 
    // Gosper's hack:
    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) {
    // Do your stuff with current set
    doStuff(set);
 
    // Gosper's hack:
    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) {
    // Do your stuff with current set
    doStuff(set);
 
    // Gosper's hack:
    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) {
    // Do your stuff with current set
    DoStuff(set);
    // Gosper's hack:
    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:
    # Work with the existing set.
    DoStuff(set)
    # Gosper's hack:
    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++




// A C++ program to find size of minimum vertex
// cover using Binary Search
#include<bits/stdc++.h>
#define maxn 25
 
using namespace std;
 
// Global array to store the graph
// Note: since the array is global, all the
// elements are 0 initially
bool gr[maxn][maxn];
 
// Returns true if there is a possible subset
// of size 'k' that can be a vertex cover
bool isCover(int V, int k, int E)
{
    // Set has first 'k' bits high initially
    int set = (1 << k) - 1;
 
    int limit = (1 << V);
 
    // to mark the edges covered in each subset
    // of size 'k'
    bool vis[maxn][maxn];
 
    while (set < limit)
    {
        // Reset visited array for every subset
        // of vertices
        memset(vis, 0, sizeof vis);
 
        // set counter for number of edges covered
        // from this subset of vertices to zero
        int cnt = 0;
 
        // selected vertex cover is the indices
        // where 'set' has its bit high
        for (int j = 1, v = 1 ; j < limit ; j = j << 1, v++)
        {
            if (set & j)
            {
                // Mark all edges emerging out of this
                // vertex visited
                for (int k = 1 ; k <= V ; k++)
                {
                    if (gr[v][k] && !vis[v][k])
                    {
                        vis[v][k] = 1;
                        vis[k][v] = 1;
                        cnt++;
                    }
                }
            }
        }
 
        // If the current subset covers all the edges
        if (cnt == E)
            return true;
 
        // Generate previous combination with k bits high
        // set & -set = (1 << last bit high in set)
        int c = set & -set;
        int r = set + c;
        set = (((r^set) >> 2) / c) | r;
    }
    return false;
}
 
// Returns answer to graph stored in gr[][]
int findMinCover(int n, int m)
{
    // Binary search the answer
    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;
    }
 
    // at the end of while loop both left and
    // right will be equal,/ as when they are
    // not, the while loop won't exit the minimum
    // size vertex cover = left = right
    return left;
}
 
// Inserts an edge in the graph
void insertEdge(int u, int v)
{
    gr[u][v] = 1;
    gr[v][u] = 1;  // Undirected graph
}
 
// Driver code
int main()
{
    /*
            6
           /
          1 ----- 5   vertex cover = {1, 2}
         /|\
        3 | \
        \ |  \
          2   4   */
    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;
 
 
    // Let us create another graph
    memset(gr, 0, sizeof gr);
    /*
           2 ---- 4 ---- 6
          /|      |
        1  |      |   vertex cover = {2, 3, 4}
         \ |      |
           3 ---- 5    */
 
    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




// A Java program to find size of minimum vertex
// cover using Binary Search
class GFG
{
 
static final int maxn = 25;
 
// Global array to store the graph
// Note: since the array is global, all the
// elements are 0 initially
static boolean [][]gr = new boolean[maxn][maxn];
 
// Returns true if there is a possible subset
// of size 'k' that can be a vertex cover
static boolean isCover(int V, int k, int E)
{
    // Set has first 'k' bits high initially
    int set = (1 << k) - 1;
 
    int limit = (1 << V);
 
    // to mark the edges covered in each subset
    // of size 'k'
    boolean [][]vis = new boolean[maxn][maxn];;
 
    while (set < limit)
    {
        // Reset visited array for every subset
        // of vertices
        for(int i = 0; i < maxn; i++)
        {
            for(int j = 0; j < maxn; j++)
            {
                vis[i][j] = false;
            }
        }
        // set counter for number of edges covered
        // from this subset of vertices to zero
        int cnt = 0;
 
        // selected vertex cover is the indices
        // where 'set' has its bit high
        for (int j = 1, v = 1 ; j < limit ; j = j << 1, v++)
        {
            if ((set & j) != 0)
            {
                // Mark all edges emerging out of this
                // vertex visited
                for (int co = 1 ; co <= V ; co++)
                {
                    if (gr[v][co] && !vis[v][co])
                    {
                        vis[v][co] = true;
                        vis[co][v] = true;
                        cnt++;
                    }
                }
            }
        }
 
        // If the current subset covers all the edges
        if (cnt == E)
            return true;
 
        // Generate previous combination with k bits high
        // set & -set = (1 << last bit high in set)
        int co = set & -set;
        int ro = set + co;
        set = (((ro^set) >> 2) / co) | ro;
    }
    return false;
}
 
// Returns answer to graph stored in gr[][]
static int findMinCover(int n, int m)
{
    // Binary search the answer
    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;
    }
 
    // at the end of while loop both left and
    // right will be equal,/ as when they are
    // not, the while loop won't exit the minimum
    // size vertex cover = left = right
    return left;
}
 
// Inserts an edge in the graph
static void insertEdge(int u, int v)
{
    gr[u][v] = true;
    gr[v][u] = true; // Undirected graph
}
 
// Driver code
public static void main(String[] args)
{
    /*
            6
        /
        1 ----- 5 vertex cover = {1, 2}
        /|\
        3 | \
        \ | \
        2 4 */
    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");
 
 
    // Let us create another graph
    for(int i = 0; i < maxn; i++)
    {
        for(int j = 0; j < maxn; j++)
        {
            gr[i][j] = false;
        }
    }
    /*
        2 ---- 4 ---- 6
        /|     |
        1 |     | vertex cover = {2, 3, 4}
        \ |     |
        3 ---- 5 */
 
    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");
 
}
}
 
// This code is contributed by Rajput-Ji


Python3




# A Python3 program to find size of minimum
# vertex cover using Binary Search
 
# Returns true if there is a possible subSet
# of size 'k' that can be a vertex cover
def isCover(V, k, E):
     
    # Set has first 'k' bits high initially
    Set = (1 << k) - 1
 
    limit = (1 << V)
 
    # to mark the edges covered in each
    # subSet of size 'k'
    vis = [[None] * maxn for i in range(maxn)]
 
    while (Set < limit):
         
        # ReSet visited array for every
        # subSet of vertices
        vis = [[0] * maxn for i in range(maxn)]
 
        # Set counter for number of edges covered
        # from this subSet of vertices to zero
        cnt = 0
 
        # selected vertex cover is the
        # indices where 'Set' has its bit high
        j = 1
        v = 1
        while(j < limit):
            if (Set & j):
                 
                # Mark all edges emerging out of 
                # this vertex visited
                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 the current subSet covers all the edges
        if (cnt == E):
            return True
 
        # Generate previous combination with k bits high
        # Set & -Set = (1 << last bit high in Set)
        c = Set & -Set
        r = Set + c
        Set = (((r ^ Set) >> 2) // c) | r
    return False
 
# Returns answer to graph stored in gr[][]
def findMinCover(n, m):
     
    # Binary search the answer
    left = 1
    right = n
    while (right > left):
        mid = (left + right) >> 1
        if (isCover(n, mid, m) == False):
            left = mid + 1
        else:
            right = mid
 
    # at the end of while loop both left and
    # right will be equal,/ as when they are
    # not, the while loop won't exit the
    # minimum size vertex cover = left = right
    return left
 
# Inserts an edge in the graph
def insertEdge(u, v):
    gr[u][v] = 1
    gr[v][u] = 1 # Undirected graph
 
# Driver code
maxn = 25
 
# Global array to store the graph
# Note: since the array is global, 
# all the elements are 0 initially
gr = [[None] * maxn for i in range(maxn)]
 
#
#     6
#     /
#     1 ----- 5 vertex cover = {1, 2}
#     /|\
# 3 | \
# \ | \
#     2 4
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))
 
# Let us create another graph
gr = [[0] * maxn for i in range(maxn)]
 
#
#     2 ---- 4 ---- 6
#     /|     |
# 1 |     | vertex cover = {2, 3, 4}
#     \ |     |
#     3 ---- 5
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))
 
# This code is contributed by PranchalK


Javascript




// A JavaScript program to find size of minimum vertex
// cover using Binary Search
 
const maxn = 25;
 
// Global array to store the graph
// Note: since the array is global, all the
// elements are false initially
const gr = Array.from({ length: maxn }, () => new Array(maxn).fill(false));
 
// Returns true if there is a possible subset
// of size 'k' that can be a vertex cover
function isCover(V, k, E) {
    // Set has first 'k' bits high initially
    let set = (1 << k) - 1;
 
    const limit = 1 << V;
 
    // to mark the edges covered in each subset
    // of size 'k'
    const vis = Array.from({ length: maxn }, () => new Array(maxn).fill(false));
 
    while (set < limit) {
        // Reset visited array for every subset
        // of vertices
        for(let i = 0; i < maxn; i++) {
            for(let j = 0; j < maxn; j++) {
                vis[i][j] = false;
            }
        }
 
        // set counter for number of edges covered
        // from this subset of vertices to zero
        let cnt = 0;
 
        // selected vertex cover is the indices
        // where 'set' has its bit high
        for (let j = 1, v = 1 ; j < limit ; j = j << 1, v++) {
            if ((set & j) !== 0) {
                // Mark all edges emerging out of this
                // vertex visited
                for (let co = 1 ; co <= V ; co++) {
                    if (gr[v][co] && !vis[v][co]) {
                        vis[v][co] = true;
                        vis[co][v] = true;
                        cnt++;
                    }
                }
            }
        }
 
        // If the current subset covers all the edges
        if (cnt === E) {
            return true;
        }
 
        // Generate previous combination with k bits high
        // set & -set = (1 << last bit high in set)
        const cO = set & -set;
        const rO = set + cO;
        set = (((rO^set) >> 2) / cO) | rO;
    }
    return false;
}
 
// Returns answer to graph stored in gr[,]
function findMinCover(n, m) {
    // Binary search the answer
    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;
        }
    }
 
    // at the end of while loop both left and
    // right will be equal,/ as when they are
    // not, the while loop won't exit the minimum
    // size vertex cover = left = right
    return left;
}
 
// Inserts an edge in the graph
function insertEdge(u, v) {
    gr[u][v] = true;
    gr[v][u] = true; // Undirected graph
}
 
// Driver code
    /*
            6
        /
        1 ----- 5 vertex cover = {1, 2}
        /|\
        3 | \
        \ | \
        2 4 */
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");
 
// Let us create another graph
for (let i = 0; i < maxn; i++) {
for (let j = 0; j < maxn; j++) {
gr[i][j] = false;
}
}
 
/*
2 ---- 4 ---- 6
/| |
1 | | vertex cover = {2, 3, 4}
\ | |
3 ---- 5
*/
 
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");
// This code is contributed by rutikbhosale


C#




// A C# program to find size of minimum vertex
// cover using Binary Search
using System;
 
class GFG
{
 
static readonly int maxn = 25;
 
// Global array to store the graph
// Note: since the array is global, all the
// elements are 0 initially
static bool [,]gr = new bool[maxn, maxn];
 
// Returns true if there is a possible subset
// of size 'k' that can be a vertex cover
static bool isCover(int V, int k, int E)
{
    // Set has first 'k' bits high initially
    int set = (1 << k) - 1;
 
    int limit = (1 << V);
 
    // to mark the edges covered in each subset
    // of size 'k'
    bool [,]vis = new bool[maxn, maxn];;
 
    while (set < limit)
    {
        // Reset visited array for every subset
        // of vertices
        for(int i = 0; i < maxn; i++)
        {
            for(int j = 0; j < maxn; j++)
            {
                vis[i, j] = false;
            }
        }
         
        // set counter for number of edges covered
        // from this subset of vertices to zero
        int cnt = 0;
 
        // selected vertex cover is the indices
        // where 'set' has its bit high
        for (int j = 1, v = 1 ; j < limit ; j = j << 1, v++)
        {
            if ((set & j) != 0)
            {
                // Mark all edges emerging out of this
                // vertex visited
                for (int co = 1 ; co <= V ; co++)
                {
                    if (gr[v, co] && !vis[v, co])
                    {
                        vis[v, co] = true;
                        vis[co, v] = true;
                        cnt++;
                    }
                }
            }
        }
 
        // If the current subset covers all the edges
        if (cnt == E)
            return true;
 
        // Generate previous combination with k bits high
        // set & -set = (1 << last bit high in set)
        int cO = set & -set;
        int rO = set + cO;
        set = (((rO^set) >> 2) / cO) | rO;
    }
    return false;
}
 
// Returns answer to graph stored in gr[,]
static int findMinCover(int n, int m)
{
    // Binary search the answer
    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;
    }
 
    // at the end of while loop both left and
    // right will be equal,/ as when they are
    // not, the while loop won't exit the minimum
    // size vertex cover = left = right
    return left;
}
 
// Inserts an edge in the graph
static void insertEdge(int u, int v)
{
    gr[u, v] = true;
    gr[v, u] = true; // Undirected graph
}
 
// Driver code
public static void Main(String[] args)
{
    /*
            6
        /
        1 ----- 5 vertex cover = {1, 2}
        /|\
        3 | \
        \ | \
        2 4 */
    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");
 
 
    // Let us create another graph
    for(int i = 0; i < maxn; i++)
    {
        for(int j = 0; j < maxn; j++)
        {
            gr[i,j] = false;
        }
    }
    /*
        2 ---- 4 ---- 6
        /|     |
        1 |     | vertex cover = {2, 3, 4}
        \ |     |
        3 ---- 5 */
 
    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");
 
}
}
 
// This code is contributed by Rajput-Ji


Output

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



Last Updated : 06 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads