定义:并查集是一种用来管理元素分组情况的数据结构。并查集可以高效的进行如下操作,不过需要注意并查集虽然可以进行合并操作,但是无法进行分割操作。
1.查询元素是否在同一组;
2.合并元素所在的组;
结构:
并查集使用树形结构来实现的。不过是二叉树;
<1>初始化:准备n个结点表示n个元素
<2>合并操作;
<3>查询操作;
Tips:优化算法,提高运行速度:1.路径压缩;
2.高度合并;
/*
并查集模板(template)
并查集的结构为二叉树;
一:合并:给出两点关系,如果属于同一集合,进行merge
二:查:在合并时,需要先写出查,即找到该点的祖先点
三:集:merge后,将新加入的点的祖先点更新
然后,点集就因为共同的祖先点被分为不同的集合
*/
#include<iostream>
using namespace std;
#define MAX 30005
int a[MAX],pre[MAX];
int find(int x)//路径压缩的方式两种.
{
if(x!=pre[x])
//找到其祖先
pre[x]=find(pre[x]) ;
//由父节点继续向上递归查询,并将其父节点找到
return pre[x] ;
}
void merge(int x,int y)
{
//分别查询祖先节点
int prex=find(x);
int prey=find(y);
//if两者的祖先节点不一致,那么任意让二者中某一个认另一个为祖先,保证同集合
if(prex==prey)
{
return ;
}
//应该是祖先节点进行组合,而不是当前节点;
pre[prey]=prex;
a[prex]+=a[prey];
}
int main()
{
int n,m;
int k,x,y;
while(~scanf("%d%d",&n,&m))
{
if(n==0 && m==0)
{
return 0;
}
for(int i=0;i<m;i++)
{
//自身作为祖先节点
pre[i]=i;
a[i]=1;
}
for(int i=0;i<m;i++)
{
//给出集合每个集合人数,以及第一个人的编号
scanf("%d%d",&k,&x);
k--;
while(k--)
{
scanf("%d",&y);
merge(x,y);
}
}
printf("%d\n",a[find(0)]);
}
return 0;
}
未完持续更新中。。。。。。