浅谈——并查集
#include<cstdio> #include<cmath> #include<cstring> #include<iostream> using namespace std; int fa[10010];//fa[i] = a:保存a的祖先 int m,n,k = 0; int aa,bb,cc; char ma[200010]; int find(int a){//查找a的祖先 if(fa[a] == a)//如果a的祖先是a,即a就是祖先 return a;//返回祖先a else return fa[a] = find(fa[a]);//a的祖先就是a的祖先的祖先,实现一直溯源 //这个操作叫做路径压缩,是优化的思路 } void join(int x,int y){//判断x,y的祖先是不是一个祖先 int fx = find(x);//查找x的祖先 int fy = find(y);//查找y的祖先 if(fx != fy)//如果x,y的祖先不是一个祖先 fa[fx] = fy;//就让y的祖先成为a的祖先,即合并x,y } int main(){ scanf("%d %d",&n,&m); for(int i = 0;i < n;i++){ fa[i] = i;//对祖先数组初始化 } for(int i = 0;i < m;i++){ scanf("%d %d %d",&aa,&bb,&cc); if(aa == 1)//要实现归并操作 join(bb,cc);//归并二者 else//要实现查找操作 if(find(bb) == find(cc)){//如果二者的祖先是一个祖先 ma[k] = 'Y';//那么输出’y' k++;//记录查找的次数 } else{//如果二者的祖先不是一个祖先 ma[k] = 'N';//那么输出’n' k++;//记录查找的次数 } } for(int i = 0;i < m;i++){//按照输出的次数分别输出 printf("%c\n",ma[i]); } return 0; }
我知道你们都很强...我就不讲了...
快来看代码吧!我的代码很详细的!
下面就是带权并查集了!
粘一下基本思想!
int pa[100005],d[100005]; int gpa(int x) { int t = pa[x]; pa[x] = gpa(t); d[x] ^= d[t];//如果d[x]与d[t]一样,就返回0;不一样,就返回1 return pa[x]; } void Merge(int x,int y) { int fx = gpa(x); int fy = gpa(y); if(fx != fy) pa[fx] = fy; return; } int query(int x,int y) { int fx = gpa(x),fy = gpa(y); return d[x] ^ d[y]; } //注意递归边界问题
最后推荐一个大佬的blog:paopo!
如果带权并查集大家有问题,欢迎看他的blog!