并查集模板:(仅供参考模板没有过于详细的讲解)
附加ACM超时原因,printf输出,elseif判断,以及scanf同时输入
第一步,初始化数组,将数组的值赋值为下标。
int arr[1005];
void init()
{
for(int i=0;i<1005;i++)
{
arr[i]=i;
}
}
第二步,并查集的主要两个函数Union和find。
find函数是通过递归进行调用,找到当前点的老大,也就是集合的顶点,这个点会是这个集合中任意的一个数字。
Union函数是连接两个点的函数,通过调用find函数找到两个点的分属集合的顶点,将一个顶点数组的值赋值为另一个的顶点,使其变成一个集合,一个顶点。
int find(int a)
{
if(arr[a]!=a)
{
arr[a]=find(arr[a]);//注意这一步很关键,为了压缩后面搜索的时间,减少时间复杂度
}
return arr[a];
}
void Union(int a,int b)
{
int f1=find(a);
int f2=find(b);
if(f1!=f2)
{
arr[f1]=f2;
}
}
第三步,将两个点通过Union函数连接。
判断集合数的方法:
int count=0;
for(int i=1;i<=n;i++)
{
if(arr[i]==i) count++;
}
注意:要从1开始,因为0没有算进端点。