并查集通过一个一维数组实现
其本质是维护一个森林
开始时,森林中每个点都是孤立的,每个点就是一棵只有一个结点的树
之后通过一些条件,逐渐将这个树合并为一棵大树。
合并的过程就是“认爹”过程
在“认爹”过程中需要遵循“靠左原则”和“擒贼先擒王”,在每次判断两个结点是否已经在同一棵树的时候,也要注意必须求其根源,中间的父亲结点是不能说明什么的,必须要找到祖宗结点,判断两个结点的祖宗是否是同一根结点才行
并查集也称为不相交集数据结构
#include<stdio.h>
int f[1000] = { 0 };
int n, m, k, sum = 0;
void init() //初始化
{
int i;
for (i = 1; i <= n; i++)
f[i] = i;
}
int getf(int v) //找祖宗
{
if (f[v] = v) //找到了祖宗
return v;
else //如果还没有到祖宗,那么就继续查找
{
f[v] = getf(f[v]); //查找过程中会把所有中间结点和叶子的值直接赋成祖宗
return f[v];
}
}
void merge(int v, int u)
{
int t1, t2;
t1 = getf(v); //找x的祖宗
t2 = getf(u); //找u的祖宗
if (t1 != t2) //如果两者的祖宗不是同一个
{
f[t2] = t1; //最左原则,将t2的上级定为t1
}
}
int main()
{
int i, x, y;
scanf("%d%d", &n, &m);
init();
for (i = 1; i <= m; i++)
{
scanf("%d%d", &x, &y);
merge(x, y);
}
for (i = 1; i <= n; i++)
{
if (f[i] == i)
sum++;
}
printf("%d\n", sum);
return 0;
}