数据结构-并查集
来源:互联网 发布:中国大数据科学家论坛 编辑:程序博客网 时间:2024/06/09 17:55
/*******************************************************数据结构:并查集;基本功能:并查集用于处理不相交数据集合;基本操作:(1)查找一个元素的祖先(即查找这个元素属于哪个集合);(2)将两个元素所在的集合合并为一个集合;(3)删除操作,即把某个元素从它所在的集合中删除;********************************************************/#include<iostream>#include<cstring>#include<cstdio>using namespace std;const int N=30030;int n;int f[N],rank[N],num[N];void init()//初始化{ for(int i=1; i<=n; i++) f[i]=i;}int getFather(int x)//查找元素x的祖先{ if(f[x]==x) return f[x]; f[x]=getFather(f[x]);//路径压缩 return f[x];}void unionSet(int x,int y)//将两个元素所在的集合合并为一个集合{ int xx=getFather(x),yy=getFather(y); if(xx!=yy) f[xx]=yy;}/********************************************************并查集的扩展(1):记录每个集合的元素个数;在此初始化以及合并集合的时候处理一下集合的元素个数即可;********************************************************/void _init(){ int i; for(i=1; i<=n; i++) f[i]=i,num[i]=1;}void _unionSet(int x,int y){ int xx=getFather(x),yy=getFather(y); if(xx!=yy) f[xx]=yy,num[yy]+=num[xx];}/********************************************************并查集的扩展(2):并查集的删除,即把某个元素从它所在的集合中删除;即生成若干个超级父亲,每个节点的父亲都是一个超级父亲;删除就直接令自己的父亲等于自己;********************************************************/int s;void __init(){ for(int i=1; i<=n; i++) f[i]=i; s=n+1;}int __getFather(int x){ if(f[x]==x) return f[x]; f[x]=getFather(f[x]); return f[x];}void __unionSet(int x,int y){ int xx=getFather(x),yy=getFather(y); if(xx!=yy) { if(xx>n) f[yy]=xx; else if(yy>n) f[xx]=yy; else f[xx]=s,f[yy]=s,f[s]=s,s++; }}void deleteX(int x){ f[x]=x;}/********************************************************并查集的扩展(3):rank数组的应用;其基本定义是一个元素到它的祖先的路径长度;算法测试:HDU2818;题目大意:有n个箱子,然后是两种操作:①把x所在的那一摞箱子搬到y所在的那一摞上面;②询问x的下面有几个箱子;********************************************************/int getF(int x){ if(f[x]==x) return x; int t=f[x];//做完getFather之后再更新rank f[x]=getF(f[x]),rank[x]+=rank[t];//rank[x]代表x到它的祖先的距离,即x的上面还有几个箱子 return f[x];}int main(){ //freopen("C:\\Users\\Administrator\\Desktop\\kd.txt","r",stdin); char te[5]; while(~scanf("%d",&n)) { for(int i=0; i<=30000; i++) f[i]=i,num[i]=1,rank[i]=0; for(int i=0; i<n; i++) { int x,y; scanf("%s",te); if(te[0]=='M') { scanf("%d%d",&x,&y); int xx=getF(x); int yy=getF(y); if(xx!=yy) f[yy]=xx,rank[yy]=num[xx],num[xx]+=num[yy]; } else { scanf("%d",&x); printf("%d\n",num[getF(x)]-rank[x]-1); } } } return 0;}