【七十九】【算法分析与设计】并查集模板!!!并查集的实现_牛客题霸_牛客网,【模板】并查集 - 洛谷,并查集代码!!!

并查集的实现_牛客题霸_牛客网

描述

给定一个没有重复值的整形数组arr,初始时认为arr中每一个数各自都是一个单独的集合。请设计一种叫UnionFind的结构,并提供以下两个操作。

boolean isSameSet(int a, int b): 查询a和b这两个数是否属于一个集合

void union(int a, int b): 把a所在的集合与b所在的集合合并在一起,原本两个集合各自的元素以后都算作同一个集合

[要求]

如果调用isSameSet和union的总次数逼近或超过O(N),请做到单次调用isSameSet或union方法的平均时间复杂度为O(1)

输入描述:

第一行两个整数N, M。分别表示数组大小、操作次数 接下来M行,每行有一个整数opt 若opt = 1,后面有两个数x, y,表示查询(x, y)这两个数是否属于同一个集合 若opt = 2,后面有两个数x, y,表示把x, y所在的集合合并在一起

输出描述:

对于每个opt = 1的操作,若为真则输出"Yes",否则输出"No"

示例1

输入:

4 5 1 1 2 2 2 3 2 1 3 1 1 1 1 2 3

复制

输出:

No Yes Yes

复制

说明:

每次2操作后的集合为 ({1}, {2}, {3}, {4}) ({1}, {2, 3}, {4}) ({1, 2, 3}, {4})

备注:

1 \leqslant N, M \leqslant 10^61⩽N,M⩽106

保证1 \leqslant x, y \leqslant N保证1⩽x,yN

1.

递归转化为迭代,_find的递归写法转化为迭代的写法.

递归的出口是father[i]==i,所以while循环的入口在递归的出口条件前面加上一个!取反.

递归的进入下一层本来是_find(father[i]).转化为迭代就是i=father[i].

中间清理栈的迭代过程也可以想象成是递归的过程.

 
#include<bits/stdc++.h> // 引入常用的头文件
#define int long long // 定义int为长整型,以支持大数据量的处理
#define endl '\n' // 定义换行符为'\n',增加输出速度
#define p pair< long long, long long> // 定义pair类型的别名p,用于存储两个长整型的数值

using namespace std; // 使用标准命名空间

const int dx[] = { 1, -1, 0, 0 }; // 定义数组dx,用于某些方向操作,此处可能未使用
const int dy[] = { 0, 0, 1, -1 }; // 定义数组dy,用于某些方向操作,此处可能未使用

// 全局变量定义区域
int n, m; // n表示数组大小,m表示操作次数
int op, nums1, nums2; // op操作类型,nums1和nums2操作数

vector<int> father; // 并查集数组,存储每个元素的父节点
vector<int> _stack; // 辅助栈,用于路径压缩

int _find(int i) { // 并查集查找操作,带路径压缩
    while (!(father[i] == i)) { // 如果i不是自己的父节点,进行路径压缩
        i = father[i];
        _stack.push_back(i); // 将当前节点添加到栈中
    }

    while (_stack.size()) { // 当栈不为空时,进行路径压缩
        father[_stack.back()] = i; // 将栈中的每个元素的父节点设置为根节点i
        _stack.pop_back(); // 弹出栈顶元素
    }

    return i; // 返回根节点
}

int isSameSet(int x, int y) { // 检查两个元素是否属于同一个集合
    return _find(x) == _find(y); // 通过查找根节点来判断
}

void _union(int x, int y) { // 并查集合并操作
    if (_find(x) == _find(y)) { // 如果x和y已经属于同一个集合,则不操作
        return;
    } else {
        father[_find(x)] = _find(y); // 将x的根节点的父节点设置为y的根节点,完成合并
    }
}

void init() { // 读取操作和操作数
    cin >> op >> nums1 >> nums2;
}

void solveinit() { // 初始化解决方案,此处未使用
}

void solve() { // 根据操作类型执行相应的并查集操作
    solveinit();
    if (op == 1) { // 如果是查询操作
        if (isSameSet(nums1, nums2))cout << "Yes" << endl; // 如果属于同一个集合,输出"Yes"
        else cout << "No" << endl; // 否则输出"No"
    } else { // 如果是合并操作
        _union(nums1, nums2); // 合并nums1和nums2所在的集合
    }
}

signed main() { // 主函数
    ios::sync_with_stdio(false); // 禁用C和C++的同步,加速cin和cout
    cin.tie(nullptr); // 解除cin和cout的绑定
    cout.tie(nullptr);
    cout << fixed << setprecision(15); // 设置浮点数输出的精度
    cin >> n >> m; // 读入数组大小和操作次数

    father.assign(n + 1, 0); // 初始化father数组,大小为n+1
    for (int i = 0; i <= n; i++) { // 将每个元素的父节点初始化为自己
        father[i] = i;
    }

    while (m--) { // 读取m个操作并执行
        init();
        solve();
    }
}

【模板】并查集 - 洛谷

【模板】并查集

题目描述

如题,现在有一个并查集,你需要完成合并和查询操作。

输入格式

第一行包含两个整数 $$N,$$ ,表示共有 $$$$ 个元素和 $$$$ 个操作。

接下来 $$$$ 行,每行包含三个整数 $$Z_i,X_i,Y_$$ 。

当 $$Z_i=$$ 时,将 $$X_$$ 与 $$Y_$$ 所在的集合合并。

当 $$Z_i=$$ 时,输出 $$X_$$ 与 $$Y_$$ 是否在同一集合内,是的输出

Y ;否则输出 N

输出格式

对于每一个 $$Z_i=$$ 的操作,都有一行输出,每行包含一个大写字母,为 Y 或者 N

样例 #1

样例输入 #1

4 7 2 1 2 1 1 2 2 1 2 1 3 4 2 1 4 1 2 3 2 1 4

样例输出 #1

N Y N Y

提示

对于 $$30\$$ 的数据,$N \le 10$,$M \le 20$。

对于 $$70\$$ 的数据,$N \le 100$,$M \le 10^3$。

对于 $$100\$$ 的数据,$1\le N \le 10^4$,$1\le M \le 2\times 10^5$,$1 \le X_i, Y_i \le N$,$Z_i \in \{ 1, 2 \}$。

 
#include<bits/stdc++.h> // 引入常用的头文件
#define int long long // 定义int为长整型,适用于处理大数据
#define endl '\n' // 定义结束符为'\n',优化输出效率
#define p pair<long long, long long> // 定义pair的别名p,用于存储长整型的键值对

using namespace std;

const int dx[] = {1, -1, 0, 0}; // 方向数组,可能用于处理四方向问题,本代码未用到
const int dy[] = {0, 0, 1, -1}; // 方向数组,可能用于处理四方向问题,本代码未用到
//----------------------------------------------------

int n, m; // n是元素数量,m是操作次数
int op, nums1, nums2; // op是操作类型,nums1和nums2是操作的元素

vector<int> father; // 并查集的父节点数组
vector<int> _st; // 辅助栈,用于路径压缩

int _find(int i) { // 查找根节点,并应用路径压缩
    while (!(father[i] == i)) { // 如果节点i不是自己的父节点,继续向上查找
        _st.push_back(i); // 将当前节点加入栈中
        i = father[i]; // 移动到父节点
    }

    while (_st.size()) { // 路径压缩,将路径上的所有节点直接连接到根节点
        father[_st.back()] = i;
        _st.pop_back();
    }

    return i; // 返回根节点
}

bool isSameSet(int x, int y) { // 判断两个元素是否在同一集合中
    return _find(x) == _find(y);
}

void _union(int x, int y) { // 合并两个集合
    if (_find(x) == _find(y)) { // 如果已经在同一集合中,则无需合并
        return;
    } else {
        father[_find(x)] = _find(y); // 否则,将一个集合的根节点指向另一个集合的根节点
    }
}

// 初始化函数,读取输入并初始化并查集
void init() {
    cin >> n >> m;
    father.assign(n + 1, 0); // 分配并初始化并查集数组
    for (int i = 0; i <= n; i++) {
        father[i] = i; // 初始化时,每个元素的父节点是自己
    }
}

// 根据操作类型执行相应的并查集操作
void solve() {
    if (op == 1) { // 如果是合并操作
        _union(nums1, nums2);
    } else { // 如果是查询操作
        if (isSameSet(nums1, nums2)) cout << "Y" << endl; // 如果在同一集合,输出Y
        else cout << "N" << endl; // 否则输出N
    }
}

signed main() {
    ios::sync_with_stdio(false); // 提高cin和cout的效率
    cin.tie(nullptr); // 解绑cin和cout
    cout.tie(nullptr);
    cout << fixed << setprecision(15); // 设置浮点数精度
    //----------------------------------------------
    init(); // 初始化
    while (m--) { // 处理每个操作
        cin >> op >> nums1 >> nums2;
        solve();
    }
}

结尾

最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。

同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。

谢谢您的支持,期待与您在下一篇文章中再次相遇!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python从0开始学习(四)

目录 前言 1、算数运算符 1.1 //:整除运算符 1.2 %:取模操作 1.3 **&#xff1a;幂运算 2、赋值运算符 3、比较运算符 4、逻辑运算符 5、位运算符 5.1 &&#xff1a;按位与 5.2 |&#xff1a;按位或 5.3 ^&#xff1a;按位异或 5.4 ~&#xff1a;按位取反 5.5…

细粒度数据设计对于微调的重要性

原文地址&#xff1a;the-importance-of-granular-data-design-for-fine-tuning 利用数据设计来训练LLM&#xff0c;以充分利用上下文&#xff0c;同时解决“Lost-In-The-Middle”的挑战。 2024 年 5 月 2 日 介绍 对话设计师难道不是杰出的数据设计师吗&#xff1f; 请允许我详…

机器学习之基于Jupyter中国环境治理投资数据分析及可视化

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 机器学习之基于Jupyter中国环境治理投资数据分析及可视化项目是一个结合了机器学习和数据可视化技术的项目&#xf…

【算法练级js+java】重复给定字符n次

题目 Repeats the given string n times.&#xff08;复制指定的字符串n次&#xff09; 期望结果 /** * Repeats the given string n times. * * repeat(‘, 3) * // > **’ * * repeat(‘abc’, 2) * // > ‘abcabc’ * * repeat(‘abc’, 0) * // > “” **/ 代码…

一步教你网站怎么免费实现https,看这里!!

要想网站实现https访问最简单有效的方法就是安装SSL证书。只要证书安装上&#xff0c;浏览器就不会再有提示网站不安全或者访问被拦截的情况。现在我来教大家怎么去获取免费的SSL证书&#xff0c;又怎么安装来证书实现https访问。 一、选择免费SSL证书提供商 有多家机构提供免…

excel公式后面加的““是什么意思呢?

这个大体上有两种用意。 1.将数值转换成文本 VLOOKUP(F2,A:C,3,0) 举个使用VLOOKUP函数的场景&#xff0c;如下图所示&#xff0c;员工信息表A:C区域中&#xff0c;A列员工号是文本型数字&#xff0c;使用VLOOKUP函数查询找的时候&#xff0c;F列的员工号数值型、文本型都有…

SinoDB数据库的RAW TABLE

RAW表是不记录日志的永久表&#xff0c;类似于无日志模式数据库中的表。对于RAW表&#xff0c;支持对其进行更新、插入和删除操作&#xff0c;但日志是不会记录这些操作。可以在RAW表上定义索引&#xff0c;但不能在RAW表上定义唯一约束、主键约束或引用约束&#xff08;refere…

java SPI思想机制

目录 如何解释简单概括SPI 和 APISPI 实现原理&#xff08;重要-线程上下文类加载器&#xff09; 如何使用一个Demo功能介绍使用效果&#xff08;直接在本地模拟服务商提供服务&#xff09;使用效果&#xff08;通过 jar 的方式引入&#xff09; 应用分析参考文章 如何解释 简…

【Altium】AD-在原理图中如何绘制贝塞尔曲线

【更多软件使用问题请点击亿道电子官方网站】 1、 文档目标 在原理图中绘制贝塞尔曲线的方法 2、 问题场景 贝塞尔曲线主要用来描述各种波形曲线&#xff0c;如正弦、余弦曲线等。贝塞尔曲线的绘制和直线类似&#xff0c;需要固定多个顶点&#xff08;最少4个&#xff09;后即…

深度学习之基于Matlab特征匹配的手写电话号码、数字识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 在信息化日益发展的今天&#xff0c;手写电话号码和数字的识别技术显得尤为重要。这种技术不仅能够提…

包管理工具npm的安装和使用

包管理工具 管理 包 的应用软件&#xff0c;可以对 包 进行下载 安装&#xff0c;更新&#xff0c;删除&#xff0c;上传 等操作。 借助包管理工具&#xff0c;可以快速开发项目&#xff0c;提升开发效率。 包管理工具是一个通用的概念&#xff0c;很多编程语言都有包管理工…

【统计推断】-01 抽样原理之(六):三个示例

目录 一、说明二、处理有限的、大尺度的母体抽样三、非参数的估计四、连续母体抽样技巧--分箱 一、说明 对于抽样问题&#xff0c;前几期文章都是理论探讨。本篇给出若干示例&#xff0c;展现具体的情况下&#xff0c;面对数据&#xff0c;如何给出处理策略。 二、处理有限的…

73. 矩阵置零/54. 螺旋矩阵

73. 矩阵置零 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]] 思路&#x…

微信/支付宝支付服务搭建,一次性搞定!

微信支付 付款码支付 付款码支付是指用户展示微信钱包内的“付款码”给商户系统扫描后直接完成支付&#xff0c;适用于线下场所面对面收银的场景&#xff0c;例如商超、便利店、餐饮、医院、学校、电影院和旅游景区等具有明确经营地址的实体场所JSAPI支付 JSAPI支付是指商户通过…

OpenCV 库来捕获和处理视频输入和相似度测量(73)

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇:OpenCV的周期性噪声去除滤波器(70) 下一篇 :使用 OpenCV 创建视频(74) ​ 目标 如今&#xff0c;拥有数字视频录制系统供您使用是很常见的。因此&#xff0c;您最终会遇到不再处理一批图像&#xf…

连锁收银系统总仓到门店库存调拨操作教程

1、进入系统后台&#xff0c;系统后台登录网址&#xff1a; 2、点击商品>门店调拨 3、选择调出仓库和调入门店 4、可选择添加商品逐个进行调拨&#xff0c;也可以批量导入需要调拨的商品 然后点击确定。 5、新增调拨后&#xff0c;系统会显示“待出库”状态 6、仓库已经准备…

Python 中使用私有成员的子类化

1、问题背景 Python 语言中&#xff0c;变量名与访问器同名是一个非常好的特性&#xff1a; self.__value 1def value():return self.__value但是&#xff0c;当我们想要子类化一个类&#xff0c;并访问其私有成员时&#xff0c;却没有一种简单的方法。通常&#xff0c;我们…

高速、简单、安全的以太彩光,锐捷网络发布极简以太全光 3.X 方案

从 2021 年 3 月正式推出到现在&#xff0c;锐捷网络极简以太全光方案已经走进第四个年头。IT 仍在不断向前发展&#xff0c;数字化进程深入&#xff0c;数字化业务增多&#xff0c;更广泛的终端设备接入企业级园区网络&#xff0c;对园区网络提出了更高的要求&#xff0c;例如…

Flutter开发Dart中的队列(Queue)

文章目录 Dart中的队列&#xff08;Queue&#xff09;基本操作示例队列的类型队列的应用总结 Dart中的队列&#xff08;Queue&#xff09; 队列是一种抽象的数据结构&#xff0c;遵循“先进先出”&#xff08;FIFO&#xff09;的原则。这意味着最早添加的元素将首先被移除。队…

PS路径文字怎么变换的?

如果网友们没有用过钢笔工具&#xff0c;画好后的样子是什么&#xff0c;建议你看看这个方法&#xff01; 建立的路径之后&#xff0c;在编辑菜单栏里单击。 选择变换路径&#xff0c;可以改变路径文字的方向&#xff0c;点击垂直翻转即可完成方向的改变&#xff01;
最新文章