EH's Blog

题目情境#

题目链接:https://www.luogu.com.cn/problem/P3367 ↗

题目描述

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

输入格式

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

接下来 MM 行,每行包含三个整数 Zi,Xi,YiZ_i,X_i,Y_i 。

当 Zi=1Z_i=1 时,将 XiX_i 与 YiY_i 所在的集合合并。

当 Zi=2Z_i=2 时,输出 XiX_i 与 YiY_i 是否在同一集合内,是的输出 Y ;否则输出 N 。

输出格式

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

输入 #1

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

输出 #1

N
Y
N
Y
plaintext

对于 100%100\% 的数据,1≤N≤2×1051\le N\le 2\times 10^5,1≤M≤1061\le M\le 10^6,1≤Xi,Yi≤N1 \le X_i, Y_i \le N,Zi∈{1,2}Z_i \in \{ 1, 2 \}。

算法解析#

一般我们使用“合并”即可,按秩合并不太需要

image-20250417165010912

image-20250417165040782

image-20250417165059357

Python代码实现#

n, m = map(int, input().split())
pa = [i for i in range(n + 1)]
def find(x):
    if pa[x] == x:
        return x
    pa[x] = find(pa[x])
    return pa[x]
def union(x, y):
    pa[find(x)] = find(y)

for _ in range(m):
    z, x, y = map(int, input().split())
    if z == 1:
        union(x, y)
    else:
        if find(x) == find(y):
            print("Y")
        else:
            print("N")
python

C++代码实现#

//并查集 路径压缩
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N=10005;
int n,m,x,y,z;
int pa[N];

int find(int x){
  if(pa[x]==x) return x;
  return pa[x]=find(pa[x]);
}
void unset(int x,int y){
  pa[find(x)]=find(y);
}
int main(){
  cin>>n>>m;
  for(int i=1;i<=n;i++) pa[i]=i;
  while(m --){
    cin>>z>>x>>y;
    if(z==1) unset(x,y);
    else{
      if(find(x)==find(y)) puts("Y");
      else puts("N");
    }
  }
}
c
C3 并查集
https://ehnotgod.site/blog/c3-%E5%B9%B6%E6%9F%A5%E9%9B%86
Author EH
Published at August 8, 2026