普通
void MakeSet(int n){
for(int i=1;i<=n;i++)
fa[i]=i,ra[i]=1;
}
int FindSet(int x){
if(x==fa[x]) return x;
else return fa[x]=FindSet(fa[x]);//压缩路径
}
void UnionSet(int x,int y){
int a=FindSet(x),b=FindSet(y);
if(ra[a]<=ra[b]) fa[a]=b;//启发式
else fa[b]=a;
if(a==n) ra[b]++;
}
带权
void MakeSet(int n){
for(int i=1;i<=n;i++)
fa[i]=i,d[i]=0,size[i]=1;
}
int FindSet(int x){
if(x==fa[x]) return x;
int root=FindSet(fa[x]);
d[x]+=d[f[x]];
else return fa[x]=root;
}
void UnionSet(int x,int y){
int a=FindSet(x),b=FindSet(y);
if(a!=b){
fa[a]=b;
d[a]+=size[b];
size[b]+=size[a];
}
}