主要操作
1.合并集合 合并两个集合
2.查找集合 查找两个元素是否在一个集合中
朴素查找
int finds(int x)
{ while(x != f[x]) x = f[x];
return x;
}
//举列
/* 4 != f[4] /f[4] = 2继续查找
2 != f[2] /f[2] = 1
1 = f[1] /此时退出循环中
*/
//从中可以看出当 当这些点合并出一个长长的链条状时,如果你从最后一个元素开始查找,会从最后一个
//找到第一个,需要很长的时间。于是就有了路径压缩这一优化过程
优化查找
//路径压缩
int finds(int x)
{ if(x != f[x])
{
f[x] = finds(f[x]);
}
return f[x];
}
// f[4] = 2 ,f[2] = 1, f[1] = 1;
// 当x的祖先节点不等于它本身时,进行路径优化
// 4 != f[4] 此时f[4] = 2;
// f[4] = finds(f[4]) // 相当于finds(2)
// 2 != f[2] 此时f[2] = 1;
// f[2] = finds(f[2]) // 相当于finds(1)
// 此时f[1] = 1 把1往回传 个人感觉就是递归的过程
此时 f[4] = f[2] = f[1] = 1;
//预处理 每一个节点都是一颗子树
for(int i = 1; i <= n; i ++) f[i] = i;
int a, b,x,y;
scanf("%d%d",&x,&y);
a = find(x); //找到x的祖宗节点
b = find(y); //找到y的祖宗节点
f[a] = b;
//让x的祖宗节点的祖宗节点 等于y的祖宗节点
//说的有点绕口了,就是让a的祖宗节点等于b
//如果还不理解的话,你就这样想 本来x的祖宗节点就是自身(相当于二叉树的根结点)
//现在让他不等于自身,换成另外一个节点了,这个节点是y的祖宗节点
题型 1.最简单的就是合并集合,查找一下两点是否在同一个集合中
2.统计某个集合中点的个数,统计有几个集合
3.最短生成树
感兴趣的可以去找一下蓝桥杯一道真题七数码,可以用并查集做。
题目肯定得从 普及 - 提高 - 省选 慢慢来,多做题掌握