P3367 【模板】并查集
題目背景
本題數據范圍已經更新到 1≤N≤2×1051\le N\le 2\times 10^51≤N≤2×105,1≤M≤1061\le M\le 10^61≤M≤106。
題目描述
如題,現在有一個并查集,你需要完成合并和查詢操作。
輸入格式
第一行包含兩個整數 N,MN,MN,M ,表示共有 NNN 個元素和 MMM 個操作。
接下來 MMM 行,每行包含三個整數 Zi,Xi,YiZ_i,X_i,Y_iZi?,Xi?,Yi? 。
當 Zi=1Z_i=1Zi?=1 時,將 XiX_iXi? 與 YiY_iYi? 所在的集合合并。
當 Zi=2Z_i=2Zi?=2 時,輸出 XiX_iXi? 與 YiY_iYi? 是否在同一集合內,是的輸出
Y
;否則輸出 N
。
輸出格式
對于每一個 Zi=2Z_i=2Zi?=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
說明/提示
對于 15%15\%15% 的數據,N≤10N \le 10N≤10,M≤20M \le 20M≤20。
對于 35%35\%35% 的數據,N≤100N \le 100N≤100,M≤103M \le 10^3M≤103。
對于 50%50\%50% 的數據,1≤N≤1041\le N \le 10^41≤N≤104,1≤M≤2×1051\le M \le 2\times 10^51≤M≤2×105。
對于 100%100\%100% 的數據,1≤N≤2×1051\le N\le 2\times 10^51≤N≤2×105,1≤M≤1061\le M\le 10^61≤M≤106,1≤Xi,Yi≤N1 \le X_i, Y_i \le N1≤Xi?,Yi?≤N,Zi∈{1,2}Z_i \in \{ 1, 2 \}Zi?∈{1,2}。
代碼
并查集模板
數據結構
parent[i]
:記錄結點i的父結點rank[i]
:以i為根的集合的高度
初始化
void init(){for(int i=1;i<=n;i++){Rank[i]=1;parent[i]=i;}
}
查詢
int find(int x){if(parent[x]!=x)parent[x]=find(parent[x]);return parent[x];
}
合并
void Union(int x,int y){int rootx=find(x);int rooty=find(y);if(rootx==rooty)return;if(Rank[rootx]>Rank[rooty]){parent[rooty]=rootx;}else if(Rank[rootx]<Rank[rooty]){parent[rootx]=rooty;}else{parent[rooty]=rootx;Rank[rootx]++;}
}
完整代碼
#include<bits/stdc++.h>
using namespace std;
int n, m;
int parent[200005];
int Rank[200005];
void init(){for(int i=1;i<=n;i++){Rank[i]=1;parent[i]=i;}
}
int find(int x){if(parent[x]!=x)parent[x]=find(parent[x]);return parent[x];
}
void Union(int x,int y){int rootx=find(x);int rooty=find(y);if(rootx==rooty)return;if(Rank[rootx]>Rank[rooty]){parent[rooty]=rootx;}else if(Rank[rootx]<Rank[rooty]){parent[rootx]=rooty;}else{parent[rooty]=rootx;Rank[rootx]++;}
}
int main(){cin>>n>>m;init();int x,y,z;for(int i=0;i<m;i++){cin>>z>>x>>y;if(z==1){Union(x, y);}else{if(find(x)==find(y))cout<<"Y"<<endl;elsecout<<"N"<<endl;}}return 0;
}