Problema de cobertura de vértices | Conjunto 1 (Introducción y Algoritmo Aproximado)

Una cubierta de vértices de un gráfico no dirigido es un subconjunto de sus vértices, de modo que para cada borde (u, v) del gráfico, ‘u’ o ‘v’ están en la cubierta de vértices. Aunque el nombre es Vertex Cover, el conjunto cubre todos los bordes del gráfico dado. Dado un gráfico no dirigido, el problema de la cobertura de vértices es encontrar la cobertura de vértices de tamaño mínimo
Los siguientes son algunos ejemplos. 
 

VertexCover

Vertex Cover Problem es un problema NP completo conocido , es decir, no hay una solución en tiempo polinomial para esto a menos que P = NP. Sin embargo, existen algoritmos de tiempo polinómico aproximado para resolver el problema. El siguiente es un algoritmo aproximado simple adaptado del libro CLRS .

Enfoque ingenuo:

Considere todo el subconjunto de vértices uno por uno y descubra si cubre todos los bordes del gráfico. Por ej. en un gráfico que consta de solo 3 vértices, el conjunto que consta de la combinación de vértices es: {0,1,2,{0,1},{0,2},{1,2},{0,1,2}} . Usando cada elemento de este conjunto, compruebe si estos vértices cubren todos los bordes del gráfico. Por lo tanto, actualice la respuesta óptima. Y, por lo tanto, imprima el subconjunto que tenga un número mínimo de vértices que también cubra todos los bordes del gráfico.

Algoritmo aproximado para la cobertura de vértices: 
 

1) Initialize the result as {}
2) Consider a set of all edges in given graph.  Let the set be E.
3) Do following while E is not empty
...a) Pick an arbitrary edge (u, v) from set E and add 'u' and 'v' to result
...b) Remove all edges from E which are either incident on u or v.
4) Return result 

El siguiente diagrama muestra la ejecución del algoritmo aproximado anterior: 
 

vertexCover

¿Qué tan bien funciona el algoritmo anterior?  
Se puede probar que el algoritmo aproximado anterior nunca encuentra una cobertura de vértice cuyo tamaño sea más del doble del tamaño de la cobertura de vértice mínima posible (Consulte esto como prueba)
Implementación: 
Las siguientes son implementaciones en C++ y Java del algoritmo aproximado anterior. 
 

C++

// Program to print Vertex Cover of a given undirected graph
#include<iostream>
#include <list>
using namespace std;
 
// This class represents a undirected graph using adjacency list
class Graph
{
    int V;    // No. of vertices
    list<int> *adj;  // Pointer to an array containing adjacency lists
public:
    Graph(int V);  // Constructor
    void addEdge(int v, int w); // function to add an edge to graph
    void printVertexCover();  // prints vertex cover
};
 
Graph::Graph(int V)
{
    this->V = V;
    adj = new list<int>[V];
}
 
void Graph::addEdge(int v, int w)
{
    adj[v].push_back(w); // Add w to v’s list.
    adj[w].push_back(v); // Since the graph is undirected
}
 
// The function to print vertex cover
void Graph::printVertexCover()
{
    // Initialize all vertices as not visited.
    bool visited[V];
    for (int i=0; i<V; i++)
        visited[i] = false;
 
    list<int>::iterator i;
 
    // Consider all edges one by one
    for (int u=0; u<V; u++)
    {
        // An edge is only picked when both visited[u] and visited[v]
        // are false
        if (visited[u] == false)
        {
            // Go through all adjacents of u and pick the first not
            // yet visited vertex (We are basically picking an edge
            // (u, v) from remaining edges.
            for (i= adj[u].begin(); i != adj[u].end(); ++i)
            {
                int v = *i;
                if (visited[v] == false)
                {
                     // Add the vertices (u, v) to the result set.
                     // We make the vertex u and v visited so that
                     // all edges from/to them would be ignored
                     visited[v] = true;
                     visited[u]  = true;
                     break;
                }
            }
        }
    }
 
    // Print the vertex cover
    for (int i=0; i<V; i++)
        if (visited[i])
          cout << i << " ";
}
 
// Driver program to test methods of graph class
int main()
{
    // Create a graph given in the above diagram
    Graph g(7);
    g.addEdge(0, 1);
    g.addEdge(0, 2);
    g.addEdge(1, 3);
    g.addEdge(3, 4);
    g.addEdge(4, 5);
    g.addEdge(5, 6);
 
    g.printVertexCover();
 
    return 0;
}

Java

// Java Program to print Vertex
// Cover of a given undirected graph
import java.io.*;
import java.util.*;
import java.util.LinkedList;
 
// This class represents an undirected
// graph using adjacency list
class Graph
{
    private int V;   // No. of vertices
 
    // Array  of lists for Adjacency List Representation
    private LinkedList<Integer> adj[];
 
    // Constructor
    Graph(int v)
    {
        V = v;
        adj = new LinkedList[v];
        for (int i=0; i<v; ++i)
            adj[i] = new LinkedList();
    }
 
    //Function to add an edge into the graph
    void addEdge(int v, int w)
    {
        adj[v].add(w);  // Add w to v's list.
        adj[w].add(v);  //Graph is undirected
    }
 
    // The function to print vertex cover
    void printVertexCover()
    {
        // Initialize all vertices as not visited.
        boolean visited[] = new boolean[V];
        for (int i=0; i<V; i++)
            visited[i] = false;
 
        Iterator<Integer> i;
 
        // Consider all edges one by one
        for (int u=0; u<V; u++)
        {
            // An edge is only picked when both visited[u]
            // and visited[v] are false
            if (visited[u] == false)
            {
                // Go through all adjacents of u and pick the
                // first not yet visited vertex (We are basically
                //  picking an edge (u, v) from remaining edges.
                i = adj[u].iterator();
                while (i.hasNext())
                {
                    int v = i.next();
                    if (visited[v] == false)
                    {
                         // Add the vertices (u, v) to the result
                         // set. We make the vertex u and v visited
                         // so that all edges from/to them would
                         // be ignored
                         visited[v] = true;
                         visited[u]  = true;
                         break;
                    }
                }
            }
        }
 
        // Print the vertex cover
        for (int j=0; j<V; j++)
            if (visited[j])
              System.out.print(j+" ");
    }
 
    // Driver method
    public static void main(String args[])
    {
        // Create a graph given in the above diagram
        Graph g = new Graph(7);
        g.addEdge(0, 1);
        g.addEdge(0, 2);
        g.addEdge(1, 3);
        g.addEdge(3, 4);
        g.addEdge(4, 5);
        g.addEdge(5, 6);
 
        g.printVertexCover();
    }
}
 
// This code is contributed by Aakash Hasija

Python3

# Python3 program to print Vertex Cover
# of a given undirected graph
from collections import defaultdict
 
# This class represents a directed graph
# using adjacency list representation
class Graph:
 
    def __init__(self, vertices):
         
        # No. of vertices
        self.V = vertices
         
        # Default dictionary to store graph
        self.graph = defaultdict(list)
 
    # Function to add an edge to graph
    def addEdge(self, u, v):
        self.graph[u].append(v)
 
    # The function to print vertex cover
    def printVertexCover(self):
         
        # Initialize all vertices as not visited.
        visited = [False] * (self.V)
         
        # Consider all edges one by one
        for u in range(self.V):
             
            # An edge is only picked when
            # both visited[u] and visited[v]
            # are false
            if not visited[u]:
                 
                # Go through all adjacents of u and
                # pick the first not yet visited
                # vertex (We are basically picking
                # an edge (u, v) from remaining edges.
                for v in self.graph[u]:
                    if not visited[v]:
                         
                        # Add the vertices (u, v) to the
                        # result set. We make the vertex
                        # u and v visited so that all
                        # edges from/to them would
                        # be ignored
                        visited[v] = True
                        visited[u] = True
                        break
 
        # Print the vertex cover
        for j in range(self.V):
            if visited[j]:
                print(j, end = ' ')
                 
        print()
 
# Driver code
 
# Create a graph given in
# the above diagram
g = Graph(7)
g.addEdge(0, 1)
g.addEdge(0, 2)
g.addEdge(1, 3)
g.addEdge(3, 4)
g.addEdge(4, 5)
g.addEdge(5, 6)
 
g.printVertexCover()
 
# This code is contributed by Prateek Gupta

C#

// C# Program to print Vertex
// Cover of a given undirected
// graph
using System;
using System.Collections.Generic;
 
// This class represents an
// undirected graph using
// adjacency list
class Graph{
   
// No. of vertices
public int V;
 
// Array of lists for
// Adjacency List Representation
public List<int> []adj;
 
// Constructor
public Graph(int v)
{
  V = v;
  adj = new List<int>[v];
 
  for (int i = 0; i < v; ++i)
    adj[i] = new List<int>();
}
 
//Function to add an edge
// into the graph
void addEdge(int v, int w)
{
   // Add w to v's list.
  adj[v].Add(w);
   
  //Graph is undirected
  adj[w].Add(v);
}
 
// The function to print
// vertex cover
void printVertexCover()
{
  // Initialize all vertices
  // as not visited.
  bool []visited = new bool[V];
 
  // Consider all edges one
  // by one
  for (int u = 0; u < V; u++)
  {
    // An edge is only picked
    // when both visited[u]
    // and visited[v] are false
    if (visited[u] == false)
    {
      // Go through all adjacents
      // of u and pick the first
      // not yet visited vertex
      // (We are basically picking
      // an edge (u, v) from remaining
      // edges.
      foreach(int i in adj[u])
      {
        int v = i;
        if (visited[v] == false)
        {
          // Add the vertices (u, v)
          // to the result set. We
          // make the vertex u and
          // v visited so that all
          // edges from/to them would
          // be ignored
          visited[v] = true;
          visited[u] = true;
          break;
        }
      }
    }
  }
 
  // Print the vertex cover
  for (int j = 0; j < V; j++)
    if (visited[j])
      Console.Write(j + " ");
}
 
// Driver method
public static void Main(String []args)
{
  // Create a graph given in
  // the above diagram
  Graph g = new Graph(7);
  g.addEdge(0, 1);
  g.addEdge(0, 2);
  g.addEdge(1, 3);
  g.addEdge(3, 4);
  g.addEdge(4, 5);
  g.addEdge(5, 6);
 
  g.printVertexCover();
}
}
 
// This code is contributed by gauravrajput1

Javascript

<script>
// Javascript Program to print Vertex
// Cover of a given undirected graph
 
// This class represents an undirected
// graph using adjacency list
class Graph
{   
    // Constructor
    constructor(v)
    {
        this.V=v;
        this.adj = new Array(v);
        for (let i = 0; i < v; ++i)
            this.adj[i] = [];
    }
     
    // Function to add an edge into the graph
    addEdge(v, w)
    {
        this.adj[v].push(w);  // Add w to v's list.
        this.adj[w].push(v);  //Graph is undirected
    }
     
     // The function to print vertex cover
    printVertexCover()
    {
        // Initialize all vertices as not visited.
        let visited = new Array(this.V);
        for (let i = 0; i < this.V; i++)
            visited[i] = false;
  
         
  
        // Consider all edges one by one
        for (let u = 0; u < this.V; u++)
        {
            // An edge is only picked when both visited[u]
            // and visited[v] are false
            if (visited[u] == false)
            {
                // Go through all adjacents of u and pick the
                // first not yet visited vertex (We are basically
                //  picking an edge (u, v) from remaining edges.
                 
                for(let i = 0; i < this.adj[u].length; i++)
                {
                    let v = this.adj[u][i];
                    if (visited[v] == false)
                    {
                     
                         // Add the vertices (u, v) to the result
                         // set. We make the vertex u and v visited
                         // so that all edges from/to them would
                         // be ignored
                         visited[v] = true;
                         visited[u]  = true;
                         break;
                    }
                }
            }
        }
  
        // Print the vertex cover
        for (let j = 0; j < this.V; j++)
            if (visited[j])
              document.write(j+" ");
    }
}
 
// Driver method
// Create a graph given in the above diagram
let g = new Graph(7);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 3);
g.addEdge(3, 4);
g.addEdge(4, 5);
g.addEdge(5, 6);
 
g.printVertexCover();
 
// This code is contributed by patel2127
</script>

Producción: 

0 1 3 4 5 6

La Complejidad de Tiempo del algoritmo anterior es O(V + E).
Algoritmos exactos: 
aunque el problema es NP completo, se puede resolver en tiempo polinomial para los siguientes tipos de gráficos. 
1) Gráfico bipartito 
2) Gráfico de árbol
El problema para verificar si hay una cubierta de vértice de tamaño menor o igual que un número k dado también se puede resolver en tiempo polinomial si k está acotado por O (LogV) (Consulte esto )
Nosotros pronto discutiremos algoritmos exactos para la cobertura de vértices.
Este artículo es una contribución de Shubham . Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *