并查集
无权并查集(路径压缩)
并查集(非rank优化)//注意我写的第一位不能有0哦,因为我的强迫症让我不想初始化
int fa[10005];
inline int find(int u){
if ( 0==fa[u]) return fa[u]=u;
int x=u,t;
while(x!=fa[x]) x=fa[x];
while(u!=x){ t=fa[u];fa[u]=x;u=t; }
return x;
}
inline void un(int u,int v){
fa[find(u)]=find(v);
}
inline bool same_r(int u,int v){
return find(u)==find(v);
}
rank路径压缩并查集
int fa[10005];//父亲
int rank1[10005];//树的高度
inline int find(int u){
if(fa[u]==0) return fa[u]=u;
int x=u,y;
while(x!=fa[x]) x=fa[x];
while(u!=x){ y=fa[u];fa[u]=x;u=y; }
return x;
}
inline void un(int x,int y){
x = find(x);
y = find(y);
if(x==y) return;
if(rank1[x]<rank1[y]){
fa[x]=y;
}else{
fa[y]=x;
if(rank1[x]==rank1[y]) rank1[x]++;
}
}
inline bool same_r(int x,int y){
return find(x)==find(y);
}
并查集维护集合信息
一个点的所在的集合信息可以即是根结点的集合信息
int fa[10005];//父亲
int rank1[10005];//树的高度
int vis[10005];//该集合节点信息
inline int find(int u){
if(fa[u]==0) return fa[u]=u;
int x=u,y;
while(x!=fa[x]) x=fa[x];
while(u!=x){ y=fa[u];fa[u]=x;u=y; }
return x;
}
inline void un(int x,int y){
bool flag=0;
if(vis[x]==1 || vis[y]==1){
flag=1;
}
x = find(x);
y = find(y);
if(flag || vis[x] || vis[y]){
vis[x]=1;
vis[y]=1;
}
if(x==y) return;
if(rank1[x]<rank1[y]){
fa[x]=y;
}else{
fa[y]=x;
if(rank1[x]==rank1[y]) rank1[x]++;
}
}
inline bool same_r(int x,int y){
return find(x)==find(y);
}
带边权并查集
int fa[500000];
int sum[500000];
int find( int u ){
if(fa[u]==u || 0==fa[u]) return fa[u]=u;
int root=find( fa[u] );
sum[ u ]+=sum[ fa[u] ];
return fa[u]=root;
}
void un(int L,int R){
int L_root=find(L);
int R_root=find(R);
sum[L_root]=;//使用向量加减
fa[ L_root ] = R_root;
}
种类并查集
大小开为:
种类数*N
对每个区间都进行操作洛谷这篇题解写得非常好,详细地说明了群系种类并查集 : 传送门