并查集的两种基本操作,查找与合并。
1.查找根节点
查找节点x 的根节点r ,并将所有途经节点的父节点修改为根节点r 。
修改后的子树会变成一个只由叶子节点与唯一一个根节点构成的,深度为2的树。
int find_F(int x) { int r= x; while(pre[r]!= r) { /*寻找根节点*/ /*循环自下到上查找x所在枝的每个父节点*/ /*直到找到根节点为止,记录根节点*/ r= pre[r]; } int i= x, j; while(i!= r) { /*路径压缩*/ /*自下至上修改,从x 到根节点r,经过的所有节点,其父节点都修改为r */ /*将子树变成一个只由叶子节点和唯一一个根节点构成的,深度为2的树*/ j= pre[i]; pre[i]= r; i= j; } return r; }
2.合并
当给出的两个节点不在一棵树上时,合并两棵树,把其中一个根节点变为另一个根节点的子节点。
void join(intx,int y) { int a=find_F(x); int b=find_F(y); /*每次对x 调用find_F()函数,都会再次刷新x 和其所有父节点*/ if(a!=b) { /*如果两节点的根节点不同,则他们不连通*/ /*则将根节点a 变成根节点b 的子节点,把两棵树合为一棵*/ pre[a]=b; /*需要注意的是:此时节点a 的其他子节点,其父节点还是a*/ } }
3.初始化
void into() { /*初始化*/ for (int i= 1; i<= maxn; i ++) { /*每个节点一开始的父节点是自己*/ pre[i]= i; } }