概念:
初始状态所有点自成一个集合
包括两个基本操作:
1.把两个集合合并成一个大集合
2.查询点x和y是否属于同一个集合
优化:
按秩合并:
维护树的深度size,把深度小树的当儿子,将其根节点作为深度较大的树的树根的子节点合并
时间复杂度O(logn)
路径压缩:
找到x的根节点后,把路径上所有的节点都直接接到根节点上
时间复杂度O(logn)
code:
#include<iostream> #include<cstdio> #include<algorithm> #define maxn 100010 using namespace std; struct bcj{ int fa[maxn]; int size[maxn]; void init(int n){ for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=n;i++) size[i]=1; } int f(int x){ return fa[x]=(fa[x]==x)?x:f(fa[x]);//"fa[x]="为路径压缩,把x直接连到根节点上 } void u(int x,int y){ x=f(x);y=f(y); if(x==y) return ;//return一定要紧跟着上一行写,防止加其他东西的时候出现非法操作 if(size[x]>size[y]) swap(x,y); size[y]+=size[x]; fa[x]=y;//这3行代码为按秩合并,把小的树接到大的树上 } }s; int main(){ int n,m; cin>>n>>m; s.init(n); for(int i=1;i<=m;i++){ int x,y,z; cin>>z>>x>>y; if(z==1) s.u(x,y); else cout<<((s.f(x)==s.f(y))?"Y":"N")<<endl; } return 0; }
题目传送门:洛谷P3367