最小权顶点覆盖问题-优先队列分支限界法-C++

问题描述:

给定一个赋权无向图 G=(V,E),每个顶点 v∈V 都有一个权值 w(v)。如果 U⊆V,U⊆V,且对任意(u,v)∈E 有 u∈U 或 v∈U,就称 U 为图 G 的一个顶点覆盖。G 的最小权顶点覆盖是指 G 中所含顶点权之和最小的顶点覆盖。对于给定的无向图 G,设计一个优先队列式分支限界法,计算 G 的最小权顶点覆盖。

算法设计:

为了找到最小权顶点覆盖,这里我们采取优先队列分支限界法来搜索该问题的解空间树。该问题的解空间是一颗子集树,因为对于图中的每一个点,都只有两种选择,加入U集合和不加入U集合,如果扩展开来就会成为一颗二叉树。

要采用优先队列来求解该问题,对于堆中的每一个节点,都有一个目前所选的点的集合,我们需要维护那些已经被选入U集合的点,同时维护当前的点权和,这样每次我们都从堆中选出当前扩展出的节点中点权和最小的一个来扩展,特别的,当点权相同时,我们通过判断当前覆盖集的大小来选择覆盖集大的来扩展。

因为我们采用的是优先队列来查找,我们的目标只是求出一个解,每次从堆中选出的节点都是当前的所有扩展出节点中点权和最小的一个,如果当前节点的状态已经实现了覆盖,那么说明当前已经是最优解了,我们可以直接返回结果。

对于该问题,我们发现无法对每个节点的右儿子进行限界:
因为当右儿子加入U集和时,点权和是不会发生改变的,虽然不加入会让点权和更小,但是不要忽略我们的目标是实现顶点覆盖,我们不扩展右儿子节点就无法保证实现覆盖,所以对右儿子的扩展是必须的。

特别的,在对于当前节点是否覆盖的判断实现中,在这里我们用一个set集合来存储当前U集合顶点可以扩展出的所有节点,这样我们每次查询当前是否覆盖只需要判断set中的元素数目是否等于所有点的数目,这样就可以做到O(1)时间的查询。

对于该问题我们的具体算法流程:
1.读入图的信息,同时初始化优先队列,加入初始的节点。
2.每次从队列中取出当前权值和最小的节点信息,判断是否实现完全覆盖。如果已经是一个完全覆盖集,直接退出搜索,返回结果集。否则需要扩展该结点的左右儿子结点。(对应的,左儿子表示将该结点加入U集合,右儿子代表直接跳过该点)。
3.如果发现当前节点的深度已经大于了节点数目,则说明当前已经搜完所有节点到达了叶子结点,若没有实现完全覆盖则直接退出即可。否则继续进行下一步搜索。

流程图:

在这里插入图片描述

代码:

#include <bits/stdc++.h>
using namespace std;struct Node {int dep; // 深度,第几层就是处理第几个点int val; // 权值vector<int>U; // U集合set<int>st; // 覆盖集Node(int dep, int val, vector<int>U, set<int>st):dep(dep), val(val), U(U), st(st) {}friend bool operator < (const Node &w1, const Node &w2) {if(w1.val == w2.val){return w1.st.size() < w2.st.size();}return w1.val > w2.val;}friend ostream& operator<<(ostream& os, const Node& p){cout << "dep:" << p.dep << " val:" << p.val << " U:";for(int i:p.U){cout << i << " ";}cout << " st:";for(int i:p.st){cout << i << " ";}return os;}
};struct Whopxx{int n;vector<int>W; // 点权vector<vector<int>>G; // 图vector<int>bst;int bestVal;Whopxx(int n,vector<int> w, vector<pair<int,int>> vt):n(n) {W = w;bst.resize(n + 1);G.resize(n + 1);for(auto [u, v]:vt){G[u].push_back(v);G[v].push_back(u);}}void work(){priority_queue<Node>q;q.push(Node(1, 0, {}, {}));while(q.size()){Node node = q.top(); q.pop();cout << node << endl;if(is_cover(node)){ // 当前节点实现全覆盖for(int i: node.U){bst[i] = 1;}bestVal = node.val;break;}if(node.dep > n){ // 搜完叶子结点仍未覆盖continue;}else{Node lnode = add(node, node.dep); q.push(lnode); // 左Node rnode = uadd(node);q.push(rnode); // 右}}}bool is_cover(Node &node){ // 判断是否为覆盖集return node.st.size() == n;}Node add(Node node, int u){ // 加入node.U.push_back(u); // 加入Unode.val += W[u];node.dep += 1;node.st.insert(u);for(auto v: G[u]){node.st.insert(v);}return node;}Node uadd(Node node){node.dep += 1;return node;}
};int main(){ freopen("input.txt","r", stdin);freopen("output.txt", "w", stdout);int n, m;cin >> n >> m;vector<int>w(n + 1);for(int i = 1; i <= n; i++) cin >> w[i];vector<pair<int,int>>vt;for(int i = 1; i <= m; i++){int u, v;cin >> u >> v;vt.push_back({u, v});}Whopxx wx(n, w, vt);wx.work();cout << wx.bestVal << endl;vector<int>ans = wx.bst;for(int i = 1;i <= n; i++){cout << ans[i] << ' ';}fclose(stdin);fclose(stdout);return 0;
}
/*7 7
1 100 1 1 1 100 10
1 6
2 4
2 5
3 6
4 5
4 6
6 75 4
1 100 1 1 1
1 2
3 2
4 2
5 24 3
1 100 1 1
1 2
3 2
4 24 3
1 3 1 1
1 2
3 2
4 24 4
1 2 10 10
1 2
2 3
3 4
4 1*/

实验测试结果及分析:

测试数据:
input.txt
在这里插入图片描述

根据该数据的建图如下:
在这里插入图片描述

通过运行程序得到:
output.txt
在这里插入图片描述

在该输出结果中,dep代表当前节点所在的深度,val当代表前的点权和,U是所选点的集合,st是当前的覆盖集。通过按优先队列的出点顺序来打印每一个节点的信息,我们可以很清晰的看到整个搜索的过程。

最后两行是问题的最优解,我们选择1,3,4这三个点加入U集合,实现总点权为3的最小顶点覆盖。

复杂度分析:若没有使用优先队列,没有剪枝,直接进行搜索,对于每一个点都有两种情况,也就是最多会扩展2^ n个节点,最坏情况下的时间复杂度为O(2^n),但是由于使用了优先队列来加速查找的过程,由于剪枝策略的存在会使时间复杂度大幅度降低,所以实际的运行时间会远低于该最坏情况下的时间复杂度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/41754.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

提取重复数据

直接上控制台代码&#xff1a; Module Module1Sub Main()Console.WriteLine("请输入数据&#xff0c;以""&#xff0c;""相隔&#xff1a;")Dim str As String Console.ReadLineDim result From x In str.Split(",")Group By x Int…

NTP协议格式解析

1. NTP时间戳格式 SNTP使用在RFC 1305 及其以前的版本所描述标准NTP时间戳的格式。与因特网标准标准一致&#xff0c; NTP 数据被指定为整数或定点小数&#xff0c;位以big-endian风格从左边0位或者高位计数。除非不这样指定&#xff0c;全部数量都将设成unsigned的类型&#…

Android Graphics 显示系统 - 监测、计算FPS的工具及设计分析

“ 在Android图像显示相关的开发、调试、测试过程中&#xff0c;如何能有效地评估画面的流畅度及监测、计算图层渲染显示的实时FPS呢&#xff1f;本篇文章将会提供一种实用、灵巧的思路。” 01 设计初衷 面对开发测试中遇到的卡顿掉帧问题&#xff0c;如何在复现卡顿的过程中持…

代码随想录算法训练营第四十五天| 300.最长递增子序列、 674. 最长连续递增序列、 718. 最长重复子数组

300.最长递增子序列 题目链接&#xff1a;300.最长递增子序列 文档讲解&#xff1a;代码随想录 状态&#xff1a;不会&#xff0c;递推状态的时候只想着如何从dp[i-1]推导dp[i]&#xff0c;没想过可能需要枚举dp[0-i] 思路&#xff1a; 找出所有比自己小的数字的dp[j],在这些dp…

SpringBoot 实现视频分段播放(通过进度条来加载视频)

需求&#xff1a;现在我本地电脑中有一个文件夹&#xff0c;文件夹中都是视频&#xff0c;需要实现视频播放的功能。 问题&#xff1a;如果通过类似 SpringBoot static 文件夹的方式来实现&#xff0c;客户端要下载好完整的视频之后才可以播放&#xff0c;并且服务端也会占用大…

秋招突击——7/5——设计模式知识点补充——适配器模式、代理模式和装饰器模式

文章目录 引言正文适配器模式学习篮球翻译适配器 面试题 代理模式学习面试题 装饰器模式学习装饰模式总结 面试题 总结 引言 为了一雪前耻&#xff0c;之前腾讯面试的极其差&#xff0c;设计模式一点都不会&#xff0c;这里找了一点设计模式的面试题&#xff0c;就针对几个常考…

计算机图形学入门24:材质与外观

1.前言 想要得到一个漂亮准确的场景渲染效果&#xff0c;不只需要物理正确的全局照明算法&#xff0c;也要了解现实中各种物体的表面外观和在图形学中的模拟方式。而物体的外观和材质其实就是同一个意思&#xff0c;不同的材质在光照下就会表现出不同的外观&#xff0c;所以外观…

代理模式的实现

1. 引言 1.1 背景 代理模式&#xff08;Proxy Pattern&#xff09;是一种常用的设计模式&#xff0c;它允许通过一个代理对象来控制对另一个对象的访问。在面向对象编程的框架中&#xff0c;代理模式被广泛应用&#xff0c;尤其在Spring框架的AOP&#xff08;面向切面编程&am…

Springboot学习之用EasyExcel4导入导出数据(基于MyBatisPlus)

一、POM依赖 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><m…

AI Earth应用—— 在线使用sentinel数据VV和VH波段进行水体提取分析(昆明抚仙湖、滇池为例)

AI Earth 本文的主要目的就是对水体进行提取,这里,具体的操作步骤很简单基本上是通过,首页的数据检索,选择需要研究的区域,然后选择工具箱种的水体提取分析即可,剩下的就交给阿里云去处理,结果如下: 这是我所选取的一景影像: 详情 卫星: Sentinel-1 级别: 1 …

基于机器学习(支持向量机,孤立森林,鲁棒协方差与层次聚类)的机械振动信号异常检测算法(MATLAB 2021B)

机械设备异常检测方法流程一般如下所示。 首先利用传感器采集机械运行过程中的状态信息&#xff0c;包括&#xff0c;振动、声音、压力、温度等。然后采用合适的信号处理技术对采集到机械信号进行分析处理&#xff0c;提取能够准确反映机械运行状态的特征。最后采用合理的异常决…

C++ 什么是虚函数?什么是纯虚函数,以及区别?(通俗易懂)

&#x1f4da; 当谈到虚函数时&#xff0c;通常是指在面向对象编程中的一种机制&#xff0c;它允许在派生类中重写基类的函数&#xff0c;并且能够通过基类指针或引用调用派生类中的函数。 目录 前言 &#x1f525; 虚函数 &#x1f525; 纯虚函数 &#x1f525; 两者区别…

mac|idea导入通义灵码插件

官方教程&#xff1a;通义灵码下载安装指南_智能编码助手_AI编程_云效(Apsara Devops)-阿里云帮助中心 下载插件&#xff1a; ⇩ TONGYI Lingma - JetBrains 结果如下&#xff1a; 选择apply、ok&#xff0c;会出现弹窗&#xff0c;点击登录 可以实现&#xff1a;生成单元测…

《C++20设计模式》代理模式

文章目录 一、前言二、实现1、UML类图2、实现 一、前言 这代理模式和装饰器模式很像啊。都是套一层类。&#x1f630; 主要就是功能差别 装饰器&#xff1a; 为了强化原有类的功能。代理模式&#xff1a; 不改变原有功能&#xff0c;只是强化原有类的潜在行为。 我觉的书上有…

【基于R语言群体遗传学】-8-代际及时间推移对于变异的影响

上一篇博客&#xff0c;我们学习了在非选择下&#xff0c;以二项分布模拟遗传漂变的过程&#xff1a;【基于R语言群体遗传学】-7-遗传变异&#xff08;genetic variation&#xff09;-CSDN博客 那么我们之前有在代际之间去模拟&#xff0c;那么我们就想知道&#xff0c;遗传变…

KVM虚机调整磁盘大小(注:需重启虚拟机)

1、将磁盘大小由15G调整为25G [rootkvm ~]# virsh domblklist kvm-client #显示虚拟机硬盘列表 [rootkvm ~]# qemu-img resize /var/lib/libvirt/images/tesk-disk.qcow2 10G #扩容 [rootkvm ~]# qemu-img info /var/lib/libvirt/images/test-disk.qcow2 #查看信息 注&…

奥威BI方案:多行业、多场景,只打高端局

奥威BI方案&#xff0c;确实以其卓越的性能和广泛的应用领域&#xff0c;在高端数据分析市场中占据了一席之地。以下是对奥威BI方案的详细解析。 奥威BI方案是一款针对多行业、多场景的全面数据分析解决方案&#xff0c;它结合了大数据、云计算等先进技术&#xff0c;为企业提…

看互联网大厂如何落地AI-Agent(3)

vivo一站式AI智能体构建平台的演进实践 引言 在AI技术的浪潮中&#xff0c;vivo互联网产品平台架构团队负责人张硕分享了vivo在构建一站式AI智能体平台方面的演进实践和深刻洞见。 背景与挑战 vivo面临的挑战包括创造商业价值、降低学习成本、合规性、以及LLM&#xff08;大…

hnust 1816: 算法10-9:简单选择排序

hnust 1816: 算法10-9&#xff1a;简单选择排序 题目描述 选择排序的基本思想是&#xff1a;每一趟比较过程中&#xff0c;在n-i1(i1,2,…,n-1)个记录中选取关键字最小的记录作为有序序列中的第i个记录。 在多种选择排序中&#xff0c;最常用且形式最为简单的是简单选择排序。…

收银系统源码-收银台副屏广告

1. 功能描述 门店广告&#xff1a;双屏收银机&#xff0c;副屏广告&#xff0c;主屏和副屏同步&#xff0c;总部可统一控制广告位&#xff0c;也可以给门店开放权限&#xff0c;门店独立上传广告位&#xff1b; 2.适用场景 新店开业、门店周年庆、节假日门店活动宣传&#x…