题目
一共有 n 个数,编号是 1∼n,最开始每个数各自在一个集合中
现在要进行 m 个操作,操作共有两种:
M a b,将编号为 a 和 b 的两个数所在的集合合并,如果两个数已经在同一个集合中,则忽略这个操作
Q a b,询问编号为 a 和 b 的两个数是否在同一个集合中
输入
4 5
M 1 2
M 3 4
Q 1 2
Q 1 3
Q 3 4
输出
Yes
No
Yes
public class 并查集_合并集合 {
//初始化
public static int N = 100010;
public static int[] p = new int[N];
public static void main(String[] args) throws IOException{
//初始化,接收n和m
//将每个元素的根节点都先指向自己,注意是i是1开始
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String[] init_data = in.readLine().split(" ");
int n = Integer.parseInt(init_data[0]), m = Integer.parseInt(init_data[1]);
for (int i = 1; i<=n; i++){p[i] = i;}
//执行操作
while (m-- > 0) {
String[] data_arr = in.readLine().split(" ");
//这里将模式参数和两个int参数分出来
String model = data_arr[0];
int x = Integer.parseInt(data_arr[1]), y = Integer.parseInt(data_arr[2]);
//直接将一棵树的根节点指向另一颗树,这样就完成了合并两个树的操作
if (model.equals("M")){p[find(x)] = find(y);}
else if (model.equals("Q")) {
if (find(x)==find(y)) {System.out.println("Yes");}
else {System.out.println("No");}
}
}
}
//并查集加路径优化,所有的节点直接指向根节点,而不是指向上一个元素,将时间压缩到近乎O(1)
public static int find(int x){
if (p[x]!=x) {p[x] = find(p[x]);}
return p[x];
}
}
声明:算法思路来源为y总,详细请见https://www.acwing.com/
本文仅用作学习记录和交流