并查集初步
PS:今天入手了一台1993年产的IBM Model M弹簧轴机械键盘,真好用呀真好用~ ^_^
并查集经常借助树形数据结构来实现。
设Father[i]表示元素i所属于的集合编号。初始化Father[x]=x;即每个节点都是单独的一棵树
并查集具有两项基本操作:
- Find(i) :返回元素i所属于的集合的编号
Int Find(int x)
{
If (x!=Father[x])
Father[x]=Find(Father[x]) //此处用到了路径压缩优化
Return Father[x];
}
- Union(x,y):合并元素x和元素y所在的集合
Void Union(int x,int y)
{
Int fx=Find(x);
Int fy=Find(y);
If (fx!=fy)
Father[fy]=fx;
}
来看一个简单的例题:
Eg1:亲戚(原题网上一抓一大把T^T)
赤裸裸的并查集,不再解释了~
1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4 int n,m,p,tx,ty,i,x,y,j; 5 int f[10000]; 6 7 int find(int x) 8 { 9 if (f[x]!=x) 10 f[x]=find(f[x]); 11 return f[x]; 12 } 13 14 void iunion(int x,int y) 15 { 16 int fx,fy; 17 fx=find(x); 18 fy=find(y); 19 if (fx!=fy) 20 f[fx]=fy; 21 } 22 23 int main() 24 { 25 cin>>n>>m>>p; 26 memset(f,0,sizeof(f)); 27 for (i=1;i<=n;i++) 28 f[i]=i; 29 30 for (i=1;i<=m;i++) 31 { 32 cin>>x>>y; 33 iunion(x,y); 34 for (j=1;j<=n;j++) cout<<f[j]<<" "; 35 cout<<endl; 36 } 37 38 for (i=1;i<=p;i++) 39 { 40 cin>>x>>y; 41 tx=find(x); 42 ty=find(y); 43 if (tx==ty) cout<<"yes"<<endl; 44 else cout<<"no"<<endl; 45 } 46 }