处理何种问题:就我目前对于并查集的理解来说,并查集是一种很巧妙的数据结构,他可以将根据集合内各个元素之间的关系将其划分为几个不同类别。
性能:目前还没有直观感受,时间复杂度主要看测试数据的复杂程度。
原理:数据结构
实现步骤:while(root!=pre[root]) root=pre[root]; 线索遍历的巧妙之处
备注:代码的的核心是FiFa(); 和 根节点之间的归并。
输入样例解释:
5 3// n节点个数,m同一组的描述个数
1 2//节点1和节点2属于同一组
2 3
4 5
5 1
2 5
输出样例解释:
2 //第一组样例一共可以分为两个大的类别
4
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MaxN=10010;
int pre[MaxN];
int n,m;
int FiFa(int root)
{
int son,temp;
son=root;
while(root!=pre[root])//第一遍,提前寻找好根节点
root=pre[root];
while(son!=pre[son])//第二遍,将之前以前的根节点更新
{
temp=son;
son=pre[son];
pre[temp]=root;
}
return root;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=0;i<=n;++i) pre[i]=i; //初始赋值,将每个点的根节点赋值为自己
int ans=n;
while(m--)
{
int a,b,root1,root2;
scanf("%d%d",&a,&b);
root1=FiFa(a);
root2=FiFa(b);
if(root1!=root2)
{
--ans;//一共有多少种互不相关的集合
if(root1<root2)//个人比较喜欢让较小的当父亲节点,其实可以不用考虑大小
pre[root2]=root1; //针对于根节点和根节点的合并,不是是子节点的合并
else
pre[root1]=root2;
}
}
printf("%d\n",ans);
}
return 0;
}
原文:https://www.cnblogs.com/l1l1/p/9688168.html