洛谷 P3367 【模板】并查集 (Java)

洛谷 P3367 【模板】并查集 (Java)

传送门: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}

分析:

实现了一个并查集的数据结构,并对给定的一系列操作进行处理。

定义全局变量:
N:表示最大元素数量。
p:表示并查集的数组,用于存储每个元素的父节点。
n 和 m:分别表示元素数量和操作数量。

查找方法 find(int x):该方法用于找到元素x所在集合的根节点(即祖先节点)。通过递归查找x的父节点,直到找到根节点,同时进行路径压缩,即将查找路径上的所有节点的父节点都直接指向根节点,以减少后续查找的时间。

合并方法 union(int x, int y):该方法将两个元素所在的集合合并。首先找到x和y的根节点(即各自集合的代表元素),如果它们的根节点不同,则将其中一个集合的根节点指向另一个集合的根节点,实现合并操作。

查询方法 sear(int x, int y):该方法用于判断元素x和y是否属于同一个集合。首先找到x和y的根节点,然后比较它们的根节点是否相同,若相同则说明它们在同一个集合中,返回true,否则返回false。

主函数main():
初始化并查集数组p,使每个元素初始时都指向自己。
循环读取每个操作:
如果操作为1,则读取两个元素x和y,执行合并操作。
如果操作为2,则读取两个元素x和y,执行查询操作,并根据查询结果输出相应的结果。

代码:

import java.util.Scanner;

public class Main {
	static final int N = 10010;
	static int [] p = new int [N];
	static int n,m;
	
	// 合并
	public static void union(int x,int y) { 
		int rootx = find(x);
		int rooty = find(y);
		if(rootx!=rooty) p[rootx] = rooty;
	}
	
	// 找到x的祖宗节点
	public static int find(int x) {
		if(p[x]!=x) p[x] = find(p[x]);
		return p[x];
	}
	
	// 查询
	public static boolean sear(int x,int y) {
		int rootx = find(x);
		int rooty = find(y);
		return rootx==rooty;
	}
	
    public static void main(String[] args) {
    	Scanner sc = new Scanner(System.in);
    	n = sc.nextInt();m = sc.nextInt();
    	for(int i = 1;i <= n;i++) p[i] = i;
    	int z,x,y;
    	while(m-->0) {
    		z = sc.nextInt();x = sc.nextInt();y = sc.nextInt();
    		if(z==1) {//union
    			union(x,y);
    		}else {//search
    			if(sear(x,y)) System.out.println("Y");
    			else System.out.println("N");
    		}
    	}
    }
}
  • 35
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值