C++实现并查集

news2024/11/24 12:23:15

1.并查集原理

在一些应用问题中,需要将n个不同的元素划分成一些不相交的集合。开始时,每个元素自成一个
单元素集合,然后按一定的规律将归于同一组元素的集合合并。在此过程中要反复用到查询某一
个元素归属于那个集合的运算。适合于描述这类问题的抽象数据类型称为并查集(union-find-set)。

比如:某公司今年校招全国总共招生10人,西安招4人,成都招3人,武汉招3人,10个人来自不
同的学校,起先互不相识,每个学生都是一个独立的小团体,现给这些学生进行编号:{0, 1, 2, 3,
4, 5, 6, 7, 8, 9}; 给以下数组用来存储该小集体,数组中的数字代表:该小集体中具有成员的个数。

毕业后,学生们要去公司上班,每个地方的学生自发组织成小分队一起上路,于是:
西安学生小分队s1={0,6,7,8},成都学生小分队s2={1,4,9},武汉学生小分队s3={2,3,5}就相互认识
了,10个人形成了三个小团体。假设右三个群主0,1,2担任队长,负责大家的出行。 

集合的树形表示:

一趟火车之旅后,每个小分队成员就互相熟悉,称为了一个朋友圈。 

从上图可以看出:编号6,7,8同学属于0号小分队,该小分队中有4人(包含队长0);编号为4和9的同
学属于1号小分队,该小分队有3人(包含队长1),编号为3和5的同学属于2号小分队,该小分队有3
个人(包含队长1)。 

仔细观察数组中内融化,可以得出以下结论:
        
1. 数组的下标对应集合中元素的编号
        2. 数组中如果为负数,负号代表根,数字代表该集合中元素个数
        3. 数组中如果为非负数,代表该元素双亲在数组中的下标

在公司工作一段时间后,西安小分队中8号同学与成都小分队1号同学奇迹般的走到了一起,两个
小圈子的学生相互介绍,最后成为了一个小圈子:

现在0集合有7个人,2集合有3个人,总共两个朋友圈。
通过以上例子可知,并查集一般可以解决一下问题: 

1. 查找元素属于哪个集合
沿着数组表示树形关系以上一直找到根(即:树中中元素为负数的位置)
2. 查看两个元素是否属于同一个集合
沿着数组表示的树形关系往上一直找到树的根,如果根相同表明在同一个集合,否则不在
3. 将两个集合归并成一个集合
将两个集合中的元素合并
将一个集合名称改成另一个集合的名称
4. 集合的个数
遍历数组,数组中元素为负数的个数即为集合的个数。

2. 并查集实现

#include <iostream>
#include <vector>
using namespace std;
class UnionFindSet
{
public:
    UnionFindSet(size_t size)
        : _ufs(size, -1) {}
    // 给一个元素的编号,查找元素属于哪一个集合:
    int FindRoot(size_t index)
    {
        while (_ufs[index] >= 0)
        {
            index = _ufs[index];
        }
        return index;
    }
    // 将两个元素所在的两个集合合并成一个集合:
    bool Union(int x1, int x2)
    {
        int root1 = FindRoot(x1);
        int root2 = FindRoot(x2);
        if (root1 == root2)
            return false;
        // 将两个集合中的元素合并:
        _ufs[root1] += _ufs[root2];
        // 将其中一个集合的名称改变成另一个:
        _ufs[root2] = root1;
        return true;
    }
    // 求集合的个数:数组中负数的个数:
    int Count()
    {
        int count = 0;
        for (auto &e : _ufs)
        {
            if (e < 0)
                count++;
        }
        return count;
    }
private:
    vector<int> _ufs;
};
void TestUFS()
{
    UnionFindSet u(10);

    u.Union(0, 6);
    u.Union(7, 6);
    u.Union(7, 8);

    u.Union(1, 4);
    u.Union(4, 9);

    u.Union(2, 3);
    u.Union(2, 5);

    cout << u.Count() << endl;
}
int main()
{
    TestUFS();
    return 0;
}

3. 并查集应用

省份数量

class Solution {
public:
    int findCircleNum(vector<vector<int>>& isConnected) {
        vector<int> ufs(isConnected.size(),-1);
        auto findroot = [&ufs](int x)
        {
            while(ufs[x] >= 0)
                x = ufs[x];

            return x;
        };
        for(int i = 0; i < isConnected.size(); i++)
        {
            for(int j = 0; j < isConnected[i].size(); j++)
            {
                if(isConnected[i][j] == 1)
                {
                    int root1 = findroot(i);
                    int root2 = findroot(j);
                    if(root1 != root2)
                    {
                        ufs[root1] += ufs[root2];
                        ufs[root2] = root1;
                    }
                }
            }
        }
        int count = 0;
        for(auto& e : ufs)
        {
            if(e < 0)
                count++;
        }
        return count;
    }
};

等式方程的可满足性

class Solution {
public:
    bool equationsPossible(vector<string>& equations) {
        vector<int> ufs(26,-1);
        auto findroot = [&ufs](int x)
        {
            while(ufs[x] >= 0)
            {
                x = ufs[x];
            }
            return x;
        };
        //将相等加到一个集合中:
        for(auto& str: equations)
        {
            if(str[1] == '=')
            {
                int root1 = findroot(str[0]-'a');
                int root2 = findroot(str[3]-'a');
                if(root1 != root2)
                {
                    ufs[root1] += ufs[root2];
                    ufs[root2] = root1;
                }
            }
        }
        //判断不相等是不是在同一个集合,如果在就不满足
        for(auto& str: equations)
        {
            if(str[1] == '!')
            {
                int root1 = findroot(str[0]-'a');
                int root2 = findroot(str[3]-'a');
                if(root1 == root2)
                    return false;
            }
        }
        return true;
    }
};

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

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

相关文章

编译原理----词法分析设计

程序设计实验1 词法分析 一、实验目的&#xff1a; 通过设计编制调试一个具体的词法分析程序&#xff0c;加深对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。 二、实验内容 编制一个单词获取程序&#xff0c;从文件…

门店销售干货 | 4种不同类型的顾客VS销售技巧,直接套用!

“我就路过随便看看” “我在别人家看到的更便宜” “我自己看&#xff0c;你不要跟着我” “我下次再买” …… 在日常的门店经营过程中&#xff0c;你是否经常遇到不同类型的顾客&#xff0c;用各种不同的话拒绝你&#xff0c;最后成交的寥寥无几。 面对不同这样不同类型…

java异常总结

java异常总结 什么是异常&#xff1f; 在Java中&#xff0c;将程序执行过程中发生的不正常行为称为异常。 常见异常举例 1.算数异常ArithmeticException public class Test{public static void main(String[] args) {System.out.println(10/0);} }报错 ArithmeticExcept…

webhub123整理 中文语音识别数据集​

我们收集和整理了常用的中文语音识别数据集&#xff0c;合计超过12000小时的数据集。已经按照不同来源整理收录到 webhub123整理 中文语音识别数据集​https://www.webhub123.com/#/home/detail?projectHashid64335220&ownerUserid22053727 整理后的效果如下 ​ 每个卡片…

mysql Lock wait timeout exceeded; try restarting transaction

文章目录 一、mysql死锁及超时的原因二、mysql死锁排查思路1、show full processlist 查询当前数据库全部线程2、information_schema 一、mysql死锁及超时的原因 当在业务逻辑中看到这个错误&#xff0c;或者mysql中使用update语句更新数据报错&#xff1a; Lock wait timeout…

数影周报:丰田215万名日本客户信息被无意泄露,菜鸟将于明年初在港IPO

本周看点&#xff1a;丰田215万名日本客户信息被无意泄露&#xff1b;美光宣布吴明霞出任美光中国区总经理&#xff1b;谷歌将向Gmail用户提供暗网数据泄露报告&#xff1b;淘宝天猫集团架构调整完成&#xff1b;菜鸟计划于2024年初在香港IPO...... 数据安全那些事 丰田215万名…

体验了基于ChatGPT的谷歌翻译插件后,我把其他翻译插件移除了

最近&#xff0c;一个基于 ChatGPT 的谷歌浏览器翻译插件挺火的&#xff0c;我体验了下&#xff0c;总结下来就一个字“666”。 github 上已经有 14.9k 的 star 了 传送门&#xff1a;GitHub - yetone/openai-translator: 基于 ChatGPT API 的划词翻译浏览器插件和跨平台桌面端…

AI学术界无人后继?高校毕业生纷纷进厂,全是香饽饽

来源 | 新智元 微信号&#xff1a;AI-era 【导读】近日&#xff0c;有外媒对一批美国名校的大学生和教授进行了采访。结果显示&#xff0c;高校毕业生入职科技公司已成主流。 AI火&#xff0c;搞AI的人就火。 这不&#xff0c;据Insider最近的一次采访报道&#xff0c;科技类…

Vue3-黑马(五)

目录&#xff1a; &#xff08;1&#xff09;vue3-基础-axios-拦截器 &#xff08;2&#xff09;vue3-基础-条件与列表 &#xff08;3&#xff09;vue3- 基础-监听器 &#xff08;1&#xff09;vue3-基础-axios-拦截器 我们自己创建axios对象有一个好处&#xff0c;就是可以…

[译] Flutter 3.10 的新功能

[译] Flutter 3.10 的新功能 原文 https://medium.com/flutter/whats-new-in-flutter-3-10-b21db2c38c73 无缝的Web和移动端集成&#xff0c;Impeller稳定版的突破性图形性能&#xff0c;以及更多 欢迎使用Flutter 3.10&#xff01;我们非常期待展示我们令人惊叹的Flutter社区所…

java可视化开发工具好用不好用?

java可视化开发工具到底好用不好用&#xff1f;这是不少粉丝朋友经常询问到的一个问题。在数字化发展趋势越发明显的当下&#xff0c;java可视化开发工具可以帮助各中大型企业实现转型升级&#xff0c;它的灵活、简洁、易操作、可视化等功能优势&#xff0c;让很多客户朋友欣慰…

OLYMP‘ARTS 2023奥艺大会中国推介会在北京盛大举行

北京时间2023年5月11日16时&#xff0c;以“艺术连接世界”为主题的OLYMPARTS 2023 国际奥艺大会中国推介会在北京盛大举行。此次活动由国际奥艺委员会&#xff08;WOAC&#xff09;指导支持&#xff0c;共邀请了国外驻华机构、文旅部、央国企、国内外协会机构、知名艺术家代表…

【项目源码】智慧班牌源码 家校互联小程序源码 智慧校园云平台

智慧校园平台源码 智慧班牌源码 人脸识别技术 电子班牌源码 家校互联小程序源码 源码开发环境&#xff1a;Javaspringbootvueelement-uimysql 智慧校园系统定位于中小学教育学校&#xff0c;侧重实际应用&#xff0c;讲究实际&#xff0c;突出加强校园安全监管&#xff0c;德…

【数值模型系列】CMAQ全局属性修改

一、问题产生 在做一个月的浓度预测时&#xff0c;由于GFS只能预报16天左右&#xff0c;因此需要使用CFS气象数据来驱动WRF模型&#xff0c;但CFS在WRF4.x版本有问题&#xff0c;因此重新装了WRF3.9.1版本的WRF。 而我这里的CMAQ ICON会去取前一天的CCTM CONC制作新的ICON文件…

ImageBind 横跨六种数据模式,用向量统一 AI 语言

出品人&#xff1a;Towhee 技术团队 作者&#xff1a;顾梦佳 人工智能&#xff08;AI&#xff09;最近毋庸置疑又迎来了一个高速发展的浪潮。 目前&#xff0c;人工智能的应用已经渗透到各个领域&#xff0c;包括自然语言处理、计算机视觉、语音识别、机器人技术等&#xff0c;…

如何自己搭建Scrapy爬虫框架

前言 当你学了一段时间爬虫后&#xff0c;就会知道各种功能太多而且麻烦。还不如自己整理个框架方便的多。因此&#xff0c;从开始写爬虫程序开始&#xff0c;就会慢慢的接触到一些有关爬虫的框架、效率提升而且扩展也很方便。接下来我将会以Scrapy爬虫框架将我的学习过程记录下…

查找符合条件,且不重复的数据 +++ EXCEL的数组公式(未完成)

查找符合条件&#xff0c;且不重复的数据 1 目标问题 查找第1列&#xff0c;月份为5月&#xff0c;并且第2列不重复的数据个数有2个条件 有的版本有唯一计数&#xff0c;有的没有 2 比较简单的方法 2.1 加辅助列&#xff0c;简单公式&#xff0c;其实逻辑是更清晰的 这里主要…

【数据结构】和栈一样简单的结构——队列

【数据结构】和栈一样简单的结构——队列 一、前言1、什么是队列&#xff1f;2、使用什么结构实现&#xff1f; 二、目标三、实现1、初始化工作2、入队2.1、图解思路2.2、代码实现 3、出队3.1、图解思路3.2、代码实现 4、打印队列(用于测试)5、返回队头元素6、返回队尾元素7、返…

Android工程师复盘小米、滴滴的面试全过程,网易offer已收入囊中

背景 时间过的真快&#xff0c;16年毕业到现在也有好几年了&#xff0c;最近面试试着投了几十家Android framework工程师的岗位&#xff0c;也面试了好几家&#xff0c;其中包括滴滴出行、小米、合众新能源、网易、最终收到了网易和滴滴offer&#xff0c;小米二面挂掉&#xf…

四、Eureka注册中心集群配置

目录 需要两个eureka server项目&#xff0c;之前已经有一个springcloud-eureka 1、在springcloud项目下新建一个聚合项目springcloud-eureka2 2、修改springcloud-eureka2的pom文件&#xff0c;引入eureka-server依赖 3、增加springcloud-eureka2的启动类&#xff0c;开启…