数据结构与算法笔记7:最小生成树-Prim和Kruskal算法

常用的最小生成树的算法主要有两种,一种是Prim算法,一种是Kruskal算法。题目链接:KamaCoder 53. 寻宝(第七期模拟笔试)
在这里插入图片描述
在这里插入图片描述
这里假设有V个节点,因为我们的节点的标号是1~V,这样我们直接使用标号作为索引,不用额外的+1或者-1操作。

1. Prim算法

Prim算法基本的思路是按点来遍历,适合点比较少边比较多的稠密图,步骤是:

  1. 初始化minDist(最小生成树到每个节点的最小值),grid(图里的边权),visited(是否加入最小生成树),我们把minDist设置为长度V+1,把grid设置为长和宽分别为V+1和V+1,visited长度也是V+1。
  • minDist初始化,初始化均为一个很大的值,这里的节点的数量小于等于10000,设置为10001:
vector<int> minDist(V+1, 10001);
  • grid初始化,一开始我们设置为一个很大的值,表示任意的两个点u和v是不可达的,因为我们后面要计算节点到最小生成树的最小值,所以我们初始化为最大值,后面求最小值才是有效的:
vector<vector<int>> grid(V+1, vector<int>(V+1, 10001));
  • visited初始化,一开始所有的节点都是没有访问过的,所以我们初始化为0,表示没有访问过,后面访问过加入了最小生成树以后我们要把节点visited对应的节点的值设置为1
vector<int> visited(V+1, 0);
  1. 求离最小生成树最近的点cur,定义初始距离minVal = INT_MAX,然后遍历所有的节点 j ∈ [ 1 , V ] j\in[1,V] j[1,V],如果 m i n V a l < m i n D i s t [ j ] minVal<minDist[j] minVal<minDist[j],minVal赋值为minDist[j],cur赋值为j,所有节点遍历结束以后,我们找到了离最小生成树最近的那个点,第一个找到的cur其实是1:
int minVal = INT_MAX;    
int cur = -1;
for (int j = 1; j <= V; ++j)
{if (!visited[j] && minDist[j] < minVal) // j不在最小生成树中并且j节点到最小生成树的距离比minVal更小{minVal = minDist[j];cur = j;}
}
  1. 把节点cur加入到最小生成树里,其实就是将visited[cur]标记为1
visited[cur] = 1;
  1. 更新cur加入最小生成树以后得minDist:遍历所有节点 j ∈ [ 1 , V ] j\in[1,V] j[1,V],如果grid[cur][j] < minDist[j],那么更新minDist[j]为grid[cur][j]:
for (int j = 1; j <= V; ++j)
{if (!visited[j] && grid[cur][j] < minDist[j])// j不在最小生成树中并且cur到j的距离比j到最小生成树上一次距离小minDist[j] = grid[cur][j];
}

因为一个最小生成树有V个节点我们需要添加V-1条边,那么我们就需要遍历V-1次(minDist更新V-1次,回想我们的更新minDist使用了grid[cur][j],表示从cur到j,因为第一个顶点是没有父亲节点的,所以第一个顶点对应的minDist[1]是不会更新的,j不会为1,更新的minDist的索引是从2到V的),那我们就可以写出完整的代码了:

#include <iostream>
#include <climits>
#include <vector>
using namespace std;int main()
{int V, E;cin >> V >> E;vector<int> visited(V+1, 0);vector<int> minDist(V+1, 10001);vector<vector<int>> grid(V+1, vector<int>(V+1, 10001));for (int i = 0; i < E; ++i){int x, y, v;cin >> x >> y >> v;grid[x][y] = v;grid[y][x] = v;}for (int i = 1; i < V; ++i){int minVal = INT_MAX;    int cur = -1;for (int j = 1; j <= V; ++j){if (!visited[j] && minDist[j] < minVal){minVal = minDist[j];cur = j;}}visited[cur] = 1;for (int j = 1; j <= V; ++j){if (!visited[j] && grid[cur][j] < minDist[j])minDist[j] = grid[cur][j];}}int ans = 0;for (int i = 2; i <= V; ++i)ans += minDist[i];cout << ans << endl;
}

Kruskal算法

Prim算法基本的思路是按边来遍历,适合边比较少点比较多的稀疏图,步骤是:

  1. 对所有的边权排序,小的边权排前面,大的排后面
  2. 遍历所有边权,如果边权的起点和终点不在同一集合(属于最小生成树和不属于最小生成树),那么连接这两个起点和终点到最小生成树里,记录最小生成树的边的答案,遍历完所有边记得到答案。

判断是不是在同一集合和链接两个点到同一个集合,我们使用并查集来做。

#include <iostream>
#include <climits>
#include <vector>
#include <algorithm>
using namespace std;class UnionSet
{vector<int> father;int pathLength = 0;
public:UnionSet(int n): father(n, 0){for (int i = 0; i < n; ++i)father[i] = i;}int find(int u){return u == father[u] ? u : father[u] = find(father[u]); // 路径压缩}void Union(int u, int v){int uRoot = find(u);int vRoot = find(v);if (uRoot == vRoot)return;father[vRoot] = uRoot;}bool isSame(int u, int v){int uRoot = find(u);int vRoot = find(v);return uRoot == vRoot;}void addPathLength(int val){pathLength += val;}int GetPathLength(){return pathLength;}};
struct Edge
{int start, end, val;
};
int main()
{int V, E;cin >> V >> E;vector<Edge> edges;for (int i = 0; i < E; ++i){int x, y, v;cin >> x >> y >> v;edges.push_back({x, y, v});}sort(edges.begin(), edges.end(), [](Edge& e1, Edge& e2){return e1.val < e2.val;});UnionSet unionSet(V+1);for (int i = 0; i < edges.size(); ++i){int x = edges[i].start;int y = edges[i].end;int val = edges[i].val;if (!unionSet.isSame(x, y)){unionSet.Union(x, y);unionSet.addPathLength(val);}}cout << unionSet.GetPathLength() << endl;
}

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

队列及笔试题

队列 先进先出 使用单链表进行队尾插入 队头删除 其中带头结点直接尾插&#xff0c;不带头结点第一次操作要判断一下 但是带头结点需要malloc和free 函数传需要修改的参数方法 1、二级指针 2、带哨兵位的头结点 3、返回值 4、如果有多个值&#xff0c;用结构体封装起来…

努比亚 Z17 NX563J Root 教程三方REC刷写工具教程

教程&#xff1a;1&#xff0c;自用成功 正常链接列表 adb devices 检查fastboot链接列表 fastboot devices 解锁设备fastboot oem nubia_unlock NUBIA_NX563J 我用的解锁设备是&#xff1a;fastboot flashing unlock 1.打开开发者选项。将OEM解锁的按钮打开 2.下载附件努…

甄选范文“论企业应用系统的数据持久层架构设计”,软考高级论文,系统架构设计师论文

论文真题 数据持久层(Data Persistence Layer)通常位于企业应用系统的业务逻辑层和数据源层之间,为整个项目提供一个高层、统一、安全、并发的数据持久机制,完成对各种数据进行持久化的编程工作,并为系统业务逻辑层提供服务。它能够使程序员避免手工编写访问数据源的方法…

MQ基础:RabbitMQ真面目

同步调用方式&#xff0c;指的是发送方直接发送给接收方的形式。而这种方式在某些情况下可能出现问题&#xff0c;比如当业务逻辑变得复杂&#xff0c;同步的方式需要等待上一条指令被接收后才会继续&#xff0c;对性能的影响很大。 异步的方式&#xff0c;增加了一个消息代理…

微信小程序操作蓝牙

主要流程&#xff1a; 1.初始化蓝牙适配器openBluetoothAdapter&#xff0c;如果不成功就onBluetoothAdapterStateChange监听蓝牙适配器状态变化事件 2.startBluetoothDevicesDiscovery开始搜寻附近的蓝牙外围设备 3.onBluetoothDeviceFound监听寻找到新设备的事件&#xff0c;…

PHP爬虫淘宝商品SKU详细信息获取指南

在电子商务领域&#xff0c;获取商品的SKU&#xff08;Stock Keeping Unit&#xff0c;库存单位&#xff09;详细信息对于商家进行库存管理、订单处理和客户服务至关重要。淘宝作为中国最大的电商平台之一&#xff0c;提供了丰富的API接口&#xff0c;使得开发者能够通过PHP爬虫…

前端学习笔记-JS进阶篇-02

构造函数&数据常用函数 1、深入对象 1.1、创建对象三种方式 1. 利用对象字面量创建对象 2. 利用new Object 创建对象 3. 利用构造函数创建对象 1.2、构造函数 构造函数&#xff1a;是一种特殊的函数&#xff0c;主要用来初始化对象 使用场景&#xff1a;常规的{...} 语…

springboot购物网站源码分享

开头&#xff1a;springboot购物网站源码分享 题目&#xff1a;springboot购物网站源码分享 主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Mysql|大数据|SSM|SpringBoot|Vue|Jsp|MYSQL等)、学习资料、JAVA源码、技术咨询 文末联系获取 感兴趣可以先收藏起来&#xff…

报数游戏 - 华为OD统一考试(E卷)

2024华为OD机试&#xff08;E卷D卷C卷&#xff09;最新题库【超值优惠】Java/Python/C合集 题目描述 100个人围成一圈&#xff0c;每个人有一个编号&#xff0c;编号从1开始到100。他们从1开始依次报数&#xff0c;报到为M的人自动退出圈圈&#xff0c;然后下一个人接着从1开始…

基于SpringBoot+Vue的茶园茶农文化交流平台

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

【MySQL实战45讲4-5】索引

文章目录 索引的定义索引的常见模型哈希表有序数组二叉搜索树 InnoDB的索引模型索引维护页分裂页合并页分裂和页合并的影响避免页分裂 覆盖索引最左前缀原则索引下推 索引的定义 索引的出现其实就是为了提高数据查询的效率&#xff0c;就像书的目录一样。一本500页的书&#x…

tee命令:轻松同步输出到屏幕与文件

一、命令简介 ​tee​ 命令在 Linux 和 Unix 系统中用于读取标准输入的数据&#xff0c;并将其同时输出到标准输出和文件中。简单来说&#xff0c;tee​ 命令可以用来分割数据流&#xff0c;使其既能够被输出到屏幕&#xff0c;也能够被写入到文件中。 ​​ ‍ 二、命令参数…

基于PI控制器的车辆行驶控制系统simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 步骤一: 确定目标与测量 4.2 步骤二: 计算误差 4.3 步骤三: 设计PI控制器 4.4 步骤四: 应用控制信号 4.5 步骤五: 反馈循环 5.完整工程文件 1.课题概述 基于PI控制器的车辆行驶控制系统是一种常…

timedatectl命令:告别时间烦恼,一键同步系统时间

一、命令简介 ​timedatectl​ 命令用于查看和设置系统的时间和日期&#xff0c;以及配置时区和 NTP&#xff08;Network Time Protocol&#xff09;设置。 相关命令&#xff1a;cal ​显示日历、 date ​查看、设置日期 ‍ 二、命令参数 格式&#xff1a; timedatectl […

[Redis][集群][下]详细讲解

目录 1.集群搭建(基于 Docker)2.主节点宕机1.宕机后会发生什么&#xff1f;2.处理流程1.故障判定2.故障迁移 3.集群扩容0.前言1.把新的主节点加入到集群2.重新分配slots3.给新的主节点添加从节点 1.集群搭建(基于 Docker) 拓扑结构如下&#xff1a; 创建目录和配置&#xff1…

【Python】FeinCMS:轻量级且可扩展的Django内容管理系统

在互联网飞速发展的今天&#xff0c;内容管理系统&#xff08;CMS&#xff09;成为了网站开发中的核心工具&#xff0c;尤其对于需要频繁更新内容的企业和个人站点而言&#xff0c;CMS 提供了极大的便利。市场上有许多不同的 CMS 工具可供选择&#xff0c;其中基于 Django 框架…

在IDEA中构建Jar包,安装Jar包到Maven仓库并在Maven项目中使用

文章目录 0. 关于本文1. IDEA构建Jar包1.1 准备一份Java代码&#xff08;就是你要构建工件的代码&#xff09;1.2 进行如下步骤构建工件 2. 关于Maven3. 将Jar包安装到Maven仓库4. 使用安装的Jar包依赖 0. 关于本文 本文内容&#xff1a; 借助IDEA构建Jar包将Jar包安装到Mave…

甄选范文“论网络安全体系设计”,软考高级论文,系统架构设计师论文

论文真题 随着社会信息化的普及,计算机网络已经在各行各业得到了广泛的应用。目前,绝大多数业务处理几乎完全依赖计算机和网络执行,各种重要数据如政府文件、工资档案、财务账目和人事档案等均依赖计算机和网络进行存储与传输。另一方面,针对计算机和网络的攻击活动日益猖…

STM32-HAL库驱动DHT11温湿度传感器 --2024.9.28

目录 一、教程简介 二、驱动原理讲解 &#xff08;一&#xff09;通信4步骤 &#xff08;二&#xff09;传感器数据解析 三、CubeMX生成底层代码 &#xff08;一&#xff09;基础配置 &#xff08;二&#xff09;配置DHT11的驱动引脚 &#xff08;三&#xff09;配置串口 四…

uni-app在线预览pdf

这里推荐下载pdf.js 插件 PDF.js - Browse Files at SourceForge.net 特此注意 如果报 Promise.withResolvers is not a function 请去查看版本兼容问题 降低pdf.js版本提高node版本 下载完成后 在 static 文件夹下新建 pdf 文件夹&#xff0c;将解压文件放进 pdf 文件…