最小权顶点覆盖问题分析

问题描述:
给定一个赋权无向图 G=(V,E),每个顶点 v∈V 都有一个权值 w(v)。如果 U⊆VU⊆V,且对任意(u,v)∈E 有 u∈U 或 v∈U,就称 U 为图 G 的一个顶点覆盖。G 的最小权顶点覆盖是指 G 中所含顶点权之和最小的顶点覆盖。

算法设计:
对于给定的无向图 G,设计一个优先队列式分支限界法,计算 G 的最小权顶点覆盖。

数据输入:
由文件input.txt给出输入数据。第 1 行有 2 个正整数 n 和 m,表示给定的图 G 有 n 个顶点和 m 条边,顶点编号为 1,2,…,n。第 2 行有 n 个正整数表示 n 个顶点的权。接下来 的 m 行中,每行有 2 个正整数 u,v,表示图 G 的一条边(u,v)。

结果输出:
将计算的最小权顶点覆盖的顶点权之和以及最优解输出到文件output.txt。文件的第1行是最小权顶点覆盖顶点权之和;第2行是最优解xi(1<=i<=n),xi=0表示顶点i不在最小权顶点覆盖中,xi=1表示顶点i在最小权顶点覆盖中。

输入文件示例
input.txt
7 7
1 100 1 1 1 100 10
1 6
2 4
2 5
3 6
4 5
4 6
6 7
输出文件示例
output.txt
13
1 0 1 0 1 0 1

算法分析:

  1. 要找到最小权覆盖,要先判定该点能否加入集合,也就是判断集合V中的点是否能与U集合中的任意一点直接相连,如果当前方案不是一种顶点覆盖,直接进行剪枝。
  2. 以顶点的权重为优先级建立一个小根堆,当有活结点加入时,对点的优先级、结果向量等进行更新。每次将小根堆的堆顶结点取出进行判断。
  3. 但是无法使用界限函数对右孩子进行约束,因为如果当右孩子不加入集合U中时,那么点权和肯定更小,但是不一定能实现覆盖,所以不经过判断也要将右孩子加入到队列中去。
    顶点覆盖判断的实现:
    开辟一个数组c,用于保存与解向量x相连的顶点及其个数。令变量j从1到n,如果x[j]==0 && c[j]==0,则表示此时j结点既不是U中的点,而且也没有u中的点与其相连。
    如下图实例:
    最小权顶点覆盖问题分析_第1张图片
    此时解向量x={0,1,0,0,1,0,0,0}表示1,4号顶点此时加入解集合
    邻接点数组c={0,0,1,0,0,1,2,0}表示2,5,6号顶点与U集合({1,4})直接相连,且6号顶点与2个U中顶点直接相连
    在这里插入图片描述 满足x[j]==0&&c[j]==0(j从1到7),不是完全覆盖
    从图中可以看出不是一种完全覆盖。
    最小权顶点覆盖问题分析_第2张图片
    解向量x={0,0,1,0,0,0,1,0} 表示2,6号顶点加入解集合
    邻接点数组c={0,1,0,1,2,1,0,1} 表示1,3,7,4,5号顶点与U集合({2,6})直接相连,且4号顶点与2个U中顶点直接相连
    在这里插入图片描述 不满足 x[j]==0&&c[j]==0(j从1到7), 是完全覆盖
    从图中可以看出是一种完全覆盖,但是顶点的权值之和不一定最小。

解空间树:
最小权顶点覆盖问题分析_第3张图片
每个顶点都有两种选择,加入U集合或者不加入U集合,显然进入右子树的选择一定是比进入左子树的选择所得的权值和小,但是进入右子树不一定满足顶点覆盖,所有当试探完左子树的结果后,还需进入右子树进行测试。

将每个试探的解向量加入到顶点权值小优先的优先队列,每次取出堆顶的解向量判断能否满足完全覆盖,如果能则得出最小权覆盖的解,因为堆顶解向量满足顶点权值和最小的原则,如果不能则继续取堆顶解向量判断。

优先队列存储空间示意图:
最小权顶点覆盖问题分析_第4张图片
图示为优先队列结点中存储的顶点权值和及其对应的解向量与邻接点数组。

——关于源代码应该都能搜到,所以这里就不再赘述了。

你可能感兴趣的:(专业课)