# dsu並查集
## 模板
```cpp=
void initialise(int n,int parent[]){
for (int i=0;i<n;i++){
parent[i]=i;
}
}
int find(int x,int parent[]){
if (parent[x]==x){
return x;
}
else{
return parent[x]=find(parent[x],parent);
}
}
void merge (int x,int y,int parent[]){
int x_root=find(x,parent);
int y_root=find(y,parent);
parent[x_root]=y_root;
}
```
洛谷:P3367 【模板】并查集
https://www.luogu.com.cn/problem/P3367
```cpp=
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma")
#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define inf 2e18
#define maxn 100005
#define mod 1000000007
int parent[maxn]={0};
void initialise(int n){
for (int i=0;i<n;i++){
parent[i]=i;
}
}
int find(int x){
if (parent[x]==x){
return x;
}
else{
return parent[x]=find(parent[x]);
}
}
void merge (int x,int y){
int x_root=find(x);
int y_root=find(y);
parent[x_root]=y_root;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int n,m;
cin>>n>>m;
initialise(n);
while(m--){
int a,b,c;
cin>>a>>b>>c;
if(a==1){
merge(b,c);
}
else{
if(find(b)==find(c)){
cout<<"Y"<<endl;
}
else{
cout<<"N"<<endl;
}
}
}
}
```
## 範例練習
洛谷:P1551 亲戚
https://www.luogu.com.cn/problem/P1551
```cpp=
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma")
#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define inf 2e18
#define maxn 100005
#define mod 1000000007
int parent[maxn]={0};
void initialise(int n){
for (int i=0;i<n;i++){
parent[i]=i;
}
}
int find(int x){
if (parent[x]==x){
return x;
}
else{
return parent[x]=find(parent[x]);
}
}
void merge (int x,int y){
int x_root=find(x);
int y_root=find(y);
parent[x_root]=y_root;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int n,m,p;
cin>>n>>m>>p;
initialise(n);
for(int i=0;i<m;i++){
int a,b;
cin>>a>>b;
merge(a,b);
}
for(int i=0;i<p;i++){
int a,b;
cin>>a>>b;
if(find(a)==find(b)){
cout<<"Yes"<<endl;
}
else{
cout<<"No"<<endl;
}
}
}
```
codeforces:D1. Mocha and Diana (Easy Version)
https://codeforces.com/problemset/problem/1559/D1
題意:Mocha的樹加上某條邊,同時Diana的樹也要增加這條邊
如:Mocha的樹加上(2,5)這條邊,那麼Diana的樹也要加上(2,5)這條邊
問:在不形成有環圖的狀況下最多可增加幾條邊
(有多個解可以輸出其中一個)
其實很簡單,只要不在同一個樹就連起來
判斷:此邊不在Mocha的樹上也不在Diana的樹上就連起來
```cpp=
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define inf 2e18
#define maxn 10005
#define mod 1000000007
int tree1[maxn];
int tree2[maxn];
void initialise(int n,int vec[]){
for (int i=0;i<n;i++){
vec[i]=i;
}
}
int find(int x,int vec[]){
if (vec[x]==x){
return x;
}
else{
return vec[x]=find(vec[x],vec);
}
}
void merge (int x,int y,int vec[]){
int x_root=find(x,vec);
int y_root=find(y,vec);
vec[x_root]=y_root;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
int n,m1,m2;
cin>>n>>m1>>m2;
initialise(n,tree1);
initialise(n,tree2);
while(m1--){
int u,v;
cin>>u>>v;
merge(u,v,tree1);
}
while(m2--){
int u,v;
cin>>u>>v;
merge(u,v,tree2);
}
int ans=0;
vector<vector<int>>ans_list;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(find(i,tree1)!=find(j,tree1) and find(i,tree2)!=find(j,tree2)){
merge(i,j,tree1);
merge(i,j,tree2);
ans_list.push_back({i,j});
ans++;
}
}
}
cout<<ans<<endl;
for(auto it:ans_list){
cout<<it[0]<<" "<<it[1]<<endl;
}
}
```
## 其他類題
[leetcode:547. Number of Provinces](https://leetcode.com/problems/number-of-provinces/)
[zerojudge: d831: 畢業旅行](https://zerojudge.tw/ShowProblem?problemid=d831)
[zerojudge: d449: 垃圾信件](https://zerojudge.tw/ShowProblem?problemid=d449)
[zerojudge: c291: APCS 2017-0304-2小群體](https://zerojudge.tw/ShowProblem?problemid=c291)
[zerojudge:f677: FJCU_109_Winter_Day3_Lab1 並查集練習](https://zerojudge.tw/ShowProblem?problemid=f677)