并查集C++

news2024/11/25 3:33:02

并查集的原理

并查集(Union-Find Set)。可以把每个连通分量看成一个集合,该集合包含了连通分量中的所有点。这些点两两连通(连通性),而具体的连通方式无关紧要,就好比集合中的元素没有先后顺序之分(无序性),只有“属于”和“不属于”的区别(确定性)。在图中,每个点恰好属于一个连通分量,对应到集合表示中,每个元素恰好属于一个集合。换句话说,图的所有连通分量可以用若干个不相交集合来表示。

并查集的精妙之处在于用树来表示集合。例如,若包含点1,2,3,4,5,6的图有3个连通分量{1,3}、{2,5,6}、{4},则需要用3棵树来表示。这3棵树的具体形态无关紧要,只要有一棵树包含1、3两个点,一棵树包含2、5、6这3个点,还有一棵树只包含4这一个点即可。规定每棵树的根结点是这棵树所对应的集合的代表元(representative)。 ——摘自网络

意思就是并查集里的每一个连通分量都是一棵树,属的每个子节点,对应的都是这个树的根,而如果想让这两个连通分量合并我们只需要让一个的代表元,也就是这棵树的树根成为另一棵树的代表元,也就是另一棵树的树根的子节点。这样子这棵树的树根对应的代表元是另一棵树的树根这时,这两个连通分量就合并了。

并查集的操作

1.利用启发式合并

        启发式合并的基本原理是每次尝试将较小的集合填入较大的集合,每一个元素维护其所在集合的大小,这时并查集的时间复杂度为O(nlog_2n)。 ——《CCF中学生计算机程序设计·提高篇》

这是实现的代码:

通俗地讲就是:如果p[x]等于x,说明x本身就是树根,因此返回x;否则返回x的父结点p[x]所在树的树根(代表元)。 ——摘自网络

2.路径压缩技术

我们发现集合中只有代表原是有用的,所以在遍历到集合的其他点时可以让它们变成代表元。在启发式合并的基础上加上路径压缩可以在时间复杂度上进行很大的优化。此时的时间复杂度是O(na(n)), 这里的a(n)是阿克曼函数的反函数,大家可以去查一下阿克曼函数的证明,其实它是一个非原始递归函数,

Ackermann函数定义如下: 若m=0,返回n+1。

若m>0且n=0,返回Ackermann(m-1,1)。

若m>0且n>0,返回Ackermann(m-1,Ackermann(m,n-1))。 ——百度

你可以把它理解为一个不超过4的常数(很快很快),也就是find函数的时间复杂度为O(4)

这里大家可以看到和上面启发式合并的代码只有一个区别就是递归时当p_x!=x时的p_x改为了p_x=find(p_x)。也就是把路过的所有点都变成那个点的代表元,也就是那个点所对应的树根。并查集的效率非常高,在平摊意义下,find函数的时间复杂度几乎可以看成是常数(而union显然是常数时间)。

并查集的应用

并查集一般和Kruskal算法结合在一起,用于判定最小生成树,最小瓶颈生成树,最小瓶颈路,或者次小生成树等问题。实现代码如下:

int cmp(const int i, const int j) { return w[i]<w[j]; } 	//间接排序函数
int find(int x) { return p[x] == x ? x : p[x] = find(p[x]);}//并查集的find
int Kruskal() {
  int ans = 0;
  for(int i = 0; i < n; i++) p[i] = i; 		//初始化并查集
  for(int i = 0; i < m; i++) r[i] = i; 		//初始化边序号
  sort(r, r+m, cmp); //给边排序
  for(int i = 0; i < m; i++) {
      int e = r[i]; int x = find(u[e]); int y = find(v[e]); 
											//找出当前边两个端点所在集合编号
      if(x != y) { ans += w[e]; p[x] = y; }	//如果在不同集合,合并
  }
  return ans;

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

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

相关文章

AI 客服定制:LangChain集成订单能力

为了提高AI客服的问题解决能力&#xff0c;我们引入了LangChain自定义能力&#xff0c;并集成了订单能力。这使得AI客服可以根据用户提出的问题&#xff0c;自动调用订单接口&#xff0c;获取订单信息&#xff0c;并结合文本知识库内容进行回答。这种能力的应用&#xff0c;使得…

java:spring使用【XXXPostProcessor】添加bean定义,修改bean定义、代理bean

# 项目代码资源&#xff1a; 可能还在审核中&#xff0c;请等待。。。 https://download.csdn.net/download/chenhz2284/89433361 # 项目代码 【pom.xml】 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-start…

【pytest官方文档学习】覆盖全局变量的示例代码在8.2.x版本运行报错

我们经常会在conftest.py中定义一些fixture提供给测试方法使用&#xff0c;但是在有些测试中&#xff0c;我们用不上或者需要对其结果进行处理后再用&#xff0c;这时候&#xff0c;就需要我们对fixture进行覆盖或重写。 在学习pytest-8.2.x官方文档看到了它给出的覆盖全局fixt…

【多线程】如何使用jconsole工具查看Java线程的详细信息?

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 1. 先运行java程序&#xff01;2. 在jdk目录下的bin文件夹中找到jconsole.exe3. 新建连接4. 观察线程状态5. …

【Python安装教程】2024年最新版Python环境搭建及模块安装,保姆教程,手把手操作,不信你还不会!

前言 Python 可应用于多个平台&#xff0c;如 Windows 、 Linux 和 MacOS 。 如何检测电脑是否安装了Python&#xff1f; 按键盘winR键&#xff0c;打开运行框。输入CMD&#xff0c;回车确定。输入where Python后回车&#xff0c;如有安装则会显示Python的安装位置。如未安装…

Java web应用性能分析之【prometheus+Grafana监控springboot服务和服务器监控】

Java web应用性能分析之【java进程问题分析概叙】-CSDN博客 Java web应用性能分析之【java进程问题分析工具】-CSDN博客 Java web应用性能分析之【jvisualvm远程连接云服务器】-CSDN博客 Java web应用性能分析之【java进程问题分析定位】-CSDN博客 Java web应用性能分析之【…

利用鱼骨图进行项目问题复盘与改进

一、引言 在项目管理中&#xff0c;问题复盘是一个至关重要的环节。它不仅能帮助我们识别项目执行过程中出现的问题&#xff0c;还能促使我们深入探究问题的根本原因&#xff0c;从而采取有效的改进措施。在这个过程中&#xff0c;鱼骨图作为一种强大的工具&#xff0c;为我们…

Android 13.0 Launcher3单层模式workspace中app列表页排序功能实现

1.概述 在13.0的定制化开发中,对于Launcher3的功能定制也是好多的,而对于单层app列表页来说排序功能的开发,也是常有的功能这就需要了解加载app数据的流程,然后根据需要进行排序就可以了,接下来就来实现这个功能 如图: 2. Launcher3单层模式workspace中app列表页排序功能…

Linux-Tomcat服务配置到系统服务

目录 前言一、系统环境二、配置步骤step1 了解环境的安装路径step2 配置生成tomcat.pid文件step3 配置tomcat.service文件 三、测试systemctl命令管理Tomcat服务3.1 systemctl命令启动Tomcat服务3.2 systemctl命令查看Tomcat服务3.3 systemctl命令关闭Tomcat服务3.4 systemctl命…

【计算机网络仿真实验-实验2.4、2.5】静态路由、动态路由(RIP)

实验2.4 静态路由 1. 实验拓扑图 注意&#xff1a;有些同学不知道两个路由器之间如何用串行DCE(红线)相接&#xff0c;只需要为路由器分别增加新的HWIC-2T接口卡就好了 不知道如何添加物理接口的&#xff0c;可以查看本人计算机网络专栏中【计算机网络仿真实验——实验准备】…

JDK8-17新特性

一、JDK8新特性:Lambda表达式 1.Lambda表达式及其使用举例 Lambda是一个匿名函数&#xff0c;我们可以把Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格&#xff0c;使Java的语言表达能力…

Elasticsearch 认证模拟题 - 21

一、题目 写一个查询&#xff0c;要求查询 kibana_sample_data_ecommerce 索引&#xff0c;且 day_of_week、customer_gender、currency、type 这 4 个字段中至少两个以上。 1.1 考点 Boolean 1.2 答案 GET kibana_sample_data_ecommerce/_search {"query": {&q…

湘潭大学软件工程数据库2(题型,复习资源和计划)

文章目录 选择题关系范式事务分析E-R 图sql作业题答案链接&#xff08;仅限有官方答案的版本&#xff09;结语 现在实验全部做完了&#xff0c;实验和作业占比是百分之 40 &#xff0c;通过上图可以看出来&#xff0c;重点是 sql 语言 所以接下来主要就是学习 sql 语句怎么书写…

AirPlay技术规范及认证资讯

AirPlay是Apple开发的一种无线技术&#xff0c;允许用户将音频、视频或图片从iOS设备、Mac电脑或其他支持AirPlay的设备无线传输到支持AirPlay的接收器设备上&#xff0c;例如智能电视或音响系统。这项技术基于Wi-Fi网络&#xff0c;提供了一种便捷的方式来共享媒体内容。AirPl…

GitLab教程(二):快速上手Git

文章目录 1.将远端代码克隆到本地2.修改本地代码并提交到远程仓库3.Git命令总结git clonegit statusgit addgit commitgit pushgit log 首先&#xff0c;我在Gitlab上创建了一个远程仓库&#xff0c;用于演示使用Gitlab进行版本管理的完整流程&#xff1a; 1.将远端代码克隆到本…

C++ 18 之 函数的重载

c18函数的重载.cpp #include <iostream> #include <string.h> using namespace std;void fun4(int a) {cout << "int a: "<< a << endl; } void fun4(double a) {cout << "double a: " << a << endl; }v…

嵌入式学习——Linux高级编程复习(UDP编程)——day43

1. UDP编程——函数接口 1.1 socket 1. 定义 int socket(int domain, int type, int protocol); 2. 功能 创建一个用来进程通信的套接字,返回文件描述符 3. 参数 domain:AF_INET IPv4协议族 type:SOCK_STREAM 流式套接字 tcp传输协议…

MYSQL八、MYSQL的SQL优化

一、SQL优化 sql优化是指&#xff1a;通过对sql语句和数据库结构的调整&#xff0c;来提高数据库查询、插入、更新和删除等操作的性能和效率。 1、插入数据优化 要一次性往数据库表中插入多条记录&#xff1a; insert into tb_test values(1,tom); insert into tb_tes…

Day52 代码随想录打卡|二叉树篇---二叉搜索树中的众数

题目&#xff08;leecode T501&#xff09;&#xff1a; 给你一个含重复值的二叉搜索树&#xff08;BST&#xff09;的根节点 root &#xff0c;找出并返回 BST 中的所有 众数&#xff08;即&#xff0c;出现频率最高的元素&#xff09;。 如果树中有不止一个众数&#xff0c…

Radis初阶 Radis基本命令与在Springboot中访问Radis

阿里网盘链接 文章目录 初始NoSQL数据库对比MySQL数据库从结构方面&#xff1a;从关系方面&#xff1a;从查询方式&#xff1a;从事物方面&#xff1a; Redis入门Redis数据结构访问Radis通用命令&#xff08;tab键&#xff1a;自动补全&#xff09;KEYSDELEXISTSEXPIRETTL Str…