using namespace std;
const int MAX=1e5;
int fa[MAX];
int rk[MAX];
//连通块个数
int cc;
//初始化
void build(int n){
    for(int i=0;i<n;i++){
        fa[i]=i;
        rk[i]=0;
    }
    cc=n;
}
//查询根节点
int find(int x){
    if(x!=fa[x]){
        //路径压缩
        fa[x]=find(fa[x]);
    }
    return fa[x];
}
//判断是否为同一个集合
bool same(int x,int y){
    return find(x)==find(y);
}
//合并集合
void unite(int x,int y){
    x=find(x);
    y=find(y);
    if(x==y) return;
    //按秩合并 小挂大
    if(rk[x]<rk[y]){
        fa[x]=y;
    }else{
        fa[y]=x;
        if(rk[x]==rk[y]) rk[x]++;
    }
    //合并成功减1
    cc--;
}