顶点覆盖问题 | Set 1(介绍和近似算法)
无向图的顶点覆盖是其顶点的子集,因此对于图的每条边 (u, v),“u”或“v”都在顶点覆盖中。虽然名称是 Vertex Cover,但该集合覆盖了给定图的所有边。给定一个无向图,顶点覆盖问题是找到最小尺寸的顶点覆盖。
以下是一些示例。
顶点覆盖问题是一个已知的 NP 完全问题,即,除非 P = NP,否则没有多项式时间解决方案。不过,有近似多项式时间算法可以解决这个问题。以下是改编自 CLRS 书籍的简单近似算法。
天真的方法:
一个一个地考虑所有顶点的子集,并找出它是否覆盖了图的所有边。例如。在仅包含 3 个顶点的图中,由顶点组合组成的集合为:{0,1,2,{0,1},{0,2},{1,2},{0,1,2}} .使用该集合的每个元素检查这些顶点是否覆盖了图的所有边。因此更新最佳答案。因此打印具有最少顶点数的子集,该子集也覆盖了图的所有边。
顶点覆盖的近似算法:
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
下图展示了上述近似算法的执行情况:
上述算法的性能如何?
可以证明,上述近似算法永远不会找到一个顶点覆盖,其大小是最小可能顶点覆盖大小的两倍以上(证明参考this)
执行:
以下是上述近似算法的 C++ 和Java实现。
C++
// Program to print Vertex Cover of a given undirected graph
#include
#include
using namespace std;
// This class represents a undirected graph using adjacency list
class Graph
{
int V; // No. of vertices
list *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[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::iterator i;
// Consider all edges one by one
for (int u=0; u
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 adj[];
// Constructor
Graph(int v)
{
V = v;
adj = new LinkedList[v];
for (int i=0; i i;
// Consider all edges one by one
for (int u=0; u
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 []adj;
// Constructor
public Graph(int v)
{
V = v;
adj = new List[v];
for (int i = 0; i < v; ++i)
adj[i] = new List();
}
//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
输出:
0 1 3 4 5 6