并查集的简单实现
并查集的特点:
1.可以高效查询元素 a 和元素b是否属于同一组
2.合并元素a和元素b所在的组 (无法分割)
初始化:n个节点来表示元素,最开始没有边。
合并:从一个组的跟向另一个组连边,这样两棵树就变成了一棵树,也就把两个组合并为一个组了。
查询:为了查询两个节点是否属于同一个组,我们需要沿着树往上走,来查询包含这个元素的根上谁,如果是同一个根,则属于同一个组。
避免退化:对于每棵树,记录这棵树的高度(rank),合并时如果两棵树的rank不同,那么从rank小的向rank大的连边。
路径压缩:对于每一个节点,一旦向上走到了一次根节点,就把这个点到父亲的边改为直接连上根。
模板实现:
1 int par[maxn]; //父亲 2 int rank[maxn]; //树的高度 3 //初始化n个元素 4 void init(int n) { 5 for(int i=0; i<n;i++) { 6 par[i]=i; 7 rank[i]=0; 8 } 9 } 10 //查询树的根 11 int find(int x) { 12 if(par[x]==x) { 13 return x; 14 } 15 else return par[x]=find(par[x]); 16 } 17 //合并x和y所属集合 18 void unite(int x,int y) { 19 x=find(x); 20 y=find(y); 21 if(x==y) return; 22 23 if(rank[x] < rank[y]) { 24 par[x]=y; 25 } else { 26 par[y]=x; 27 if(rank[x]==rank[y]) rank[x]++; 28 } 29 } 30 //判断x 和y是否属于同一个 集合 31 bool same(int x,int y) { 32 return find(x) == find(y); 33 }