当前位置: 首页 > news >正文

【洛谷 P3367】【模板】并查集 题解(并查集+启发式合并)

【模板】并查集

题目描述

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

输入格式

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

接下来 M M M 行,每行包含三个整数 Z i , X i , Y i Z_i,X_i,Y_i Zi,Xi,Yi

Z i = 1 Z_i=1 Zi=1 时,将 X i X_i Xi Y i Y_i Yi 所在的集合合并。

Z i = 2 Z_i=2 Zi=2 时,输出 X i X_i Xi Y i Y_i Yi 是否在同一集合内,是的输出
Y ;否则输出 N

输出格式

对于每一个 Z i = 2 Z_i=2 Zi=2 的操作,都有一行输出,每行包含一个大写字母,为 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 % 30\% 30% 的数据, N ≤ 10 N \le 10 N10 M ≤ 20 M \le 20 M20

对于 70 % 70\% 70% 的数据, N ≤ 100 N \le 100 N100 M ≤ 1 0 3 M \le 10^3 M103

对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 1 0 4 1\le N \le 10^4 1N104 1 ≤ M ≤ 2 × 1 0 5 1\le M \le 2\times 10^5 1M2×105 1 ≤ X i , Y i ≤ N 1 \le X_i, Y_i \le N 1Xi,YiN Z i ∈ { 1 , 2 } Z_i \in \{ 1, 2 \} Zi{1,2}


思路

定义一个数组pre用于存储每个元素的父节点,sz数组用于存储每个集合的大小。在初始化时,每个元素都是一个单独的集合,父节点是自己,集合的大小为1。

root函数用于查找元素的根节点,也就是找到该元素所在集合的代表元素。这个过程是通过不断地向上查找父节点来实现的。

merge函数用于合并两个集合。先找到两个集合的根节点,如果根节点相同,说明两个集合已经是同一个集合,不需要合并。如果不同,就将较小的集合合并到较大的集合中,并更新大集合的大小。

check函数用于检查两个元素是否在同一个集合中。如果两个元素的根节点相同,说明它们在同一个集合中,打印“Y”,否则打印“N”。

在主函数中,首先读取元素的数量n和操作的数量m,然后初始化并查集。接下来进行m次操作,每次操作根据读取的操作类型z来执行合并集合或者检查元素是否在同一个集合中的操作。

使用启发式合并优化后,代码运行用时大幅度缩短。


AC代码

#include <algorithm>
#include <iostream>
#define AUTHOR "HEX9CF"
using namespace std;const int N = 1e5 + 7;int pre[N], sz[N];void init(int x) {for (int i = 1; i <= x; i++) {pre[i] = i;sz[i] = 1;}
}int root(int x) {int i = x;while (pre[i] != i) {i = pre[i];}return i;
}void merge(int x, int y) {x = root(x);y = root(y);if (x == y) {return;}if (sz[x] > sz[y]) {swap(x, y);}pre[x] = y;sz[y] += sz[x];
}void check(int x, int y) {x = root(x);y = root(y);if (x == y) {printf("Y\n");} else {printf("N\n");}
}int main() {int n, m;scanf("%d %d", &n, &m);init(n);while (m--) {int z, x, y;scanf("%d %d %d", &z, &x, &y);if (z == 1) {merge(x, y);} else {check(x, y);}}return 0;
}

相关文章:

  • c++类和对象新手保姆级上手教学(上)
  • The method toList() is undefined for the type Stream
  • 汇编的两道题
  • ES入门知识点总结
  • ChatGPT高效提问—prompt实践(智能辅导-心理咨询-职业规划)
  • 互联网加竞赛 基于计算机视觉的身份证识别系统
  • 前端工程化面试题 | 11.精选前端工程化高频面试题
  • Ubuntu忘记登录密码重置步骤
  • 使用 Spring Data JPA 和 Mybatis 结合的方式进行分页查询
  • 1414 - 期末考试成绩排名
  • 【分享】JLINK的SW调试模式连线方式
  • 【深度学习】S2 数学基础 P4 概率论
  • uniapp如何给视频组件设置图片
  • leetcode135. 分发糖果
  • 6、内网安全-横向移动WmiSmbCrackMapExecProxyChainsImpacket
  • 【腾讯Bugly干货分享】从0到1打造直播 App
  • 0x05 Python数据分析,Anaconda八斩刀
  • eclipse的离线汉化
  • ES6系列(二)变量的解构赋值
  • JavaScript 基础知识 - 入门篇(一)
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • jQuery(一)
  • Less 日常用法
  • Linux快速复制或删除大量小文件
  • Octave 入门
  • Rancher-k8s加速安装文档
  • Redis的resp协议
  • session共享问题解决方案
  • vue 个人积累(使用工具,组件)
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 创建一个Struts2项目maven 方式
  • 从零开始的webpack生活-0x009:FilesLoader装载文件
  • 记录一下第一次使用npm
  • 学习使用ExpressJS 4.0中的新Router
  • 以太坊客户端Geth命令参数详解
  • No resource identifier found for attribute,RxJava之zip操作符
  • 【干货分享】dos命令大全
  • 阿里云ACE认证学习知识点梳理
  • 不要一棍子打翻所有黑盒模型,其实可以让它们发挥作用 ...
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • 小白应该如何快速入门阿里云服务器,新手使用ECS的方法 ...
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • # MySQL server 层和存储引擎层是怎么交互数据的?
  • # Python csv、xlsx、json、二进制(MP3) 文件读写基本使用
  • ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTr
  • ### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
  • (2022 CVPR) Unbiased Teacher v2
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (C#)获取字符编码的类
  • (八)Flask之app.route装饰器函数的参数
  • (二)【Jmeter】专栏实战项目靶场drupal部署
  • (分布式缓存)Redis分片集群
  • (附源码)springboot人体健康检测微信小程序 毕业设计 012142
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理第3章 信息系统治理(一)
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)