版权声明:大佬们转载时别忘了我哦!!! https://blog.csdn.net/sun9979/article/details/87561783
并查集:union(合并),find(查找),set(集合)。
1)合并:合并两个集合。
2)查找:判断两个元素是否在一个集合。
1、首先得有一个father数组,其中father[i]=i,的意思就时father[i]表示元素i的父亲。
2、初始化!让他们都属于不同的集合,他们的父节点都是自己
for(int i = 1; i <= n; i++)
father[i] = i; //也可以是-1
3、查找!可以用递推或者递归
int findFather(int x)
{
while(x != father[x])
x = father[x];
return x;
}
//或者递归
int findFather(int x)
{
if(x == father[x]) return x;
else return findFather(father[x]);
}
4、合并!把两个集合合并为一个集合
void Union(int a, int b) //应该写大写U,小写u好像会冲突
{
int faA = findFather(a);
int faB = findFather(b);
if(faA != faB)
father[faA] = faB; //谁是谁父节点都无所谓,看想要谁,就让谁是谁的父节点
}
5、路径压缩!
以上的查找函数是没有经过优化的,在极端情况下效率极低,元素数量很多并形成一条链的时候,查找函数的效率贼低。
int findFather(int x)
{
int a = x;
while(x != father[x])
x = father[x];
while(a != fahter[a]) { //路径压缩代码,可以省略
int z = a;
a = father[a];
father[z] = x;
}
return x;
}
经典例题:
PAT–L2-007家庭房产------并查集
PAT–L2-010排座位------并查集
PAT–L2-024部落------并查集(Union函数问题)
PAT–L3-003社交集群------并查集
大致总结一下一些所求的点:
1)当时对于什么共同的兴趣或者课程的时候,应为没有直接输入id,所以应该另外设置一个数组a,首先给每一个兴趣或者课程一个father,当a[b]==0时令a[b]=i。
2)怎么求集合的总个数?
怎么求每个集合的个数
int isRoot[10000]={0};
for(int i=1;i<=n;i++){
if(isRoot[find(i)]==0) flag++;
isRoot[find(i)]++;
}