顶点覆盖问题近似算法C语言,顶点覆盖问题的NP完全证明和近似算法求解

《顶点覆盖问题的NP完全证明和近似算法求解》由会员分享,可在线阅读,更多相关《顶点覆盖问题的NP完全证明和近似算法求解(5页珍藏版)》请在人人文库网上搜索。

1、顶点覆盖问题的NP完全证明和顶点覆盖优化问题的近似算法顶点覆盖(VERTEX COVER)给定一个无向图和一个正整数,若存在,使得对任意的,都有或,则称为图的一个大小为的顶点覆盖。顶点覆盖问题的描述判定问题:VERTEX COVER输 入:无向图,正整数问 题:中是否存在一个大小为的顶点覆盖,这是一个NP完全问题顶点覆盖的NP完全性证明NP性的证明:对给定的无向图,若顶点是图的一个大小为顶点的覆盖,则可以构造一个确定性的算法,以多项式的时间验证,及对所有的,是否有或。因此顶点覆盖问题是一个NP问题。完全性的证明:我们已知团集(CLIQUE)问题是一个NP完全问题,若团集问题归约于顶点覆盖问题,。

2、即,则顶点覆盖问题就是一个NP完全问题。我们可以利用无向图的补图来说明这个问题。若向图,则的补图,其中。例如,图1(b)是图1(a)的补图。在图1(a)中有一个大小为3的团集,在图1(b)中,则有一个大小为2的顶点覆盖。显然可以在多项式时间里构造图的补图。因此,只要证明图有一个大小为的团集,当且仅当它的补图有一个大小为的顶点覆盖。(a) (b)图1无向图及补图必要性:如果中有一个大小为的团集,则它具有一个大小为个顶点的完全子图,令这个顶点集合为。令是中的任意一条边,则。所以中必有一个顶点不属于,即中必有一个顶点属于,也就是边被覆盖。因为是中的任意一条边,因此,中的边都被覆盖,所以,是的一个大小。

3、为的顶点覆盖。充分性:如果中有一个大小为的顶点覆盖,令这个顶点覆盖为,是中的任意一条边,则和至少有一个顶点属于。因此,对于任意的顶点和,若并且,则必然有,即是中一个大小为的的团集。综上所述,团集(CLIQUE)问题归约于顶点覆盖(VERTEX COVER)问题,即。所以,顶点覆盖问题是一个NP完全问题。顶点覆盖优化问题的近似算法上面已经证得,顶点覆盖问题是一个NP完全问题,因此,没有一个确定性的多项式时间算法来解它。顶点覆盖的优化问题是找出图中的最小顶点覆盖。为了用近似算法解决这个问题,假设顶点用编号,并用下面的邻接表来存放顶点与顶点之间的关联边。/*邻接表结点的数据结构*/*邻接结点的编号*。

4、/*下一个邻接顶点*/*图的邻接表头结点*/则顶点覆盖问题的近似算法的求解步骤可以叙述如下:(1)顶点的初始编号;(2)如果顶点存在关联边,转到步骤(3),否则,转到步骤(5);(3)令关联边为,把顶点和顶点登记到顶点覆盖中;(4)删去与顶点和顶点关联的所有边;(5),如果,转到步骤(2),否则,算法结束。算法的实现过程叙述如下:算法名称:顶点覆盖优化问题的近似算法;输 入:无向图的邻接表,顶点个数为;输 出:图的顶点覆盖,中的顶点个数为。/*如果存在关联边*/*则选取边的顶点*/*删去与有关联的所有边*/*删去与关联的所有边*/算法说明:这个算法用数组来存放顶点覆盖中的各个顶点,用变量来存放。

5、数组中的顶点个数。开始时,把变量初始化为0,把顶点的编号初始化为0。然后从顶点开始,如果顶点存在着关联边,就把顶点及其一个邻接点登记到数组中。并删去与顶点和顶点的所有关联边。其中,第11行的函数用来删去顶点与顶点相邻接的登记项;第17行函数用来删去顶点与顶点相邻接的登记项;第14行和20行分别把顶点和顶点的邻接表头结点的链指针置为空,从而分别删去这两个顶点与其他顶点相邻接的所有登记项。经过这样的处理,就把顶点及顶点的所有关联边删去。这种处理一直进行,直到图中的所有边都被删去为止。最后,在数组中存放着图的顶点覆盖中的各个顶点编号,变量表示数组中登记的顶点个数。图2表示了这种处理过程。图2(a)表。

6、示图的初始状态;图2(b)表示选择边,把关联边的顶点及放进数组中,并删去顶点及顶点相关联的所有边,这里删去边,及;图2(c)表示选择边,把关联该边的顶点和顶点放进数组中,并删去边,及;这个过程一直进行,图2(g)表示最后得到的结果。整个处理过程共选择了6条边上的12个顶点,作为图的一个顶点覆盖,他们是。可以看到,它不是图的最小的顶点覆盖。图2(h)表示图的一个最小的顶点覆盖,它有7个顶点,分别是。(a) (b)(c) (d)(e) (f)(g) (h)图2 算法处理过程图算法近似性能估计:下面来估计这个算法的近似性能。假定算法所选取的边集为,则这些边的关联边顶点被作为顶点覆盖中的顶点,放进数组中。因为一旦选择了某条边,例如边,则与顶点和顶点相关联的所有边均删去。再次选择第2条边时,第2条边与第1条边将不会具有公共顶点,则边集中的所有的边都不会具有公共顶点。这样放进数组中的顶点个数为,即。另一方面,图的任何一个顶点覆盖,至少包含中各条边中的一个顶点。若图的最小顶点覆盖为,则有。所以有:由此可以得到,这个算法的性能比率小于或等于2。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用贪心算法求解顶点覆盖问题C语言代码: ```c #include <stdio.h> #include <stdlib.h> #define MAX_N 100 int graph[MAX_N][MAX_N]; // 邻接矩阵表示图 int cover[MAX_N]; // 顶点覆盖集合 int visited[MAX_N]; // 标记每个顶点是否已经被覆盖 int vertex_cover(int n) { int i, j, max_deg, max_deg_idx; // 初始化顶点覆盖集合为空 for (i = 0; i < n; i++) { cover[i] = 0; } // 迭代选择未被覆盖的边中所涉及的顶点数量最多的顶点 while (1) { // 找出度数最大的未被覆盖顶点 max_deg = -1; for (i = 0; i < n; i++) { if (!visited[i]) { int deg = 0; for (j = 0; j < n; j++) { if (graph[i][j] && !visited[j]) { deg++; } } if (deg > max_deg) { max_deg = deg; max_deg_idx = i; } } } // 如果没有未被覆盖顶点,则退出循环 if (max_deg == -1) { break; } // 将该顶点加入顶点覆盖集合中,并将与之相邻的边全部标记为已经覆盖 cover[max_deg_idx] = 1; visited[max_deg_idx] = 1; for (j = 0; j < n; j++) { if (graph[max_deg_idx][j]) { visited[j] = 1; } } } // 返回顶点覆盖集合的大小 int size = 0; for (i = 0; i < n; i++) { if (cover[i]) { size++; } } return size; } int main() { int n, m; scanf("%d%d", &n, &m); // 读入图的边 int i, j; for (i = 0; i < m; i++) { int u, v; scanf("%d%d", &u, &v); graph[u][v] = graph[v][u] = 1; } // 求解顶点覆盖问题 int size = vertex_cover(n); printf("Minimum vertex cover: %d\n", size); return 0; } ``` 该代码通过邻接矩阵表示图,使用 visited 数组标记每个顶点是否已经被覆盖,使用 cover 数组表示当前顶点覆盖集合。迭代选择未被覆盖的边中所涉及的顶点数量最多的顶点,并将其加入到顶点覆盖集合中,并将与之相邻的边全部标记为已经覆盖。最后统计顶点覆盖集合的大小即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值