P3367 【模板】并查集
题目链接 https://www.luogu.com.cn/problem/P3367
并:合并。将两个不相交的集合合并,合并时需要先查找。
查:查找。查找两个节点是否在同一集合内,也就是根节点是否相同。
集:集合。将新加入的点的根节点更新。
并查集:用来检查一个图是否存在环;合并合集或者判断是否有相同的祖先关系,可以将不同的元素合并到同一个集合中,想查询的时候直接查询。
parent[i]表示i结点的父节点
rankp[i]记录深度,表示i所在的层数。避免一条长链式的结构导致查找路径时非常慢,可以引用rankp数组对此优化。
查找根节点:
int Getparent(int o) { if(o == parent[o]) return o; else { parent[o] = Getparent(parent[o]); //父节点设为根节点 return parent[o]; //返回父节点 } }
可以简写为:
int Getparent(int o) { return o == parent[o] ? o : (parent[o] = Getparent(parent[o])); }
合并:
void Union(int x,int y) { int x_root=Getparent(x); int y_root=Getparent(y); if(x_root!=y_root) parent[y_root]=x_root;//左靠,将右边的集合作为左边的子集 return; }
可以优化为:
int Union(int x,int y,int parent[],int rankp[]) { int x_root=Getparent(x); int y_root=Getparent(y); if(x_root==y_root) return 0; else { if(rankp[x_root]>rankp[y_root]) parent[y_root]=x_root; else if(rankp[y_root]>rankp[x_root]) parent[x_root]=y_root; else { parent[x_root]=y_root; rankp[y_root]++; } return 1; }
放AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 long long n,m; 4 int z,x,y; 5 int parent[20010]; 6 int rankp[20010]; 7 8 //找根节点 9 inline int Getparent(int o) 10 { 11 if(parent[o]==o) return o; 12 else return parent[o]=Getparent(parent[o]);//路径压缩 13 } 14 15 //合并 16 inline int Union(int x,int y,int parent[],int rankp[]) 17 { 18 int x_root=Getparent(x); 19 int y_root=Getparent(y); 20 if(x_root==y_root) return 0; 21 else//优化部分 22 { 23 if(rankp[x_root]>rankp[y_root]) 24 parent[y_root]=x_root; 25 else if(rankp[y_root]>rankp[x_root]) 26 parent[x_root]=y_root; 27 else 28 { 29 parent[x_root]=y_root; 30 rankp[y_root]++; 31 } 32 return 1; 33 } 34 } 35 36 //是否在同一子集 37 inline void Find(int x,int y) 38 { 39 int x_root=Getparent(x); 40 int y_root=Getparent(y); 41 if(x_root==y_root) cout<<"Y"<<endl; 42 else cout<<"N"<<endl; 43 } 44 45 int main() 46 { 47 ios::sync_with_stdio(false); 48 memset(rankp,0,sizeof(rankp)); 49 cin>>n>>m; 50 for(register int i=1;i<=n;i++) 51 parent[i]=i; 52 for(register int i=1; i<=m; i++) 53 { 54 cin>>z>>x>>y; 55 if(z==1) Union(x,y,parent,rankp); 56 else Find(x,y); 57 } 58 return 0; 59 }