实现方法很简单~ 用树来实现~所有属于同一集合的元素属于同一棵树,
这样我们就可以用数根来表示一个集合,要找到某个元素属于哪个集合
,只要找到这个元素所在的树的树根;要合并两个集合,只要合并两棵树。一般比
较方便的方法是用父亲数组Parent[]来表示树,Parent[i]就是节点i的父结点,树
根的父结点就是它本身,关于并查集的优化,可以在find的时候进行路径压缩~只有两层
int find(int x)
{
if(x!=p[x]) p[x]=find(p[x]);//每次查找的时候,都进行了压缩~
return p[x];
}
下面附上代码:
#include <iostream>
using namespace std;
int n,m,k,t,f,p[30001],rank[30001],a,b;
int find(int x)
{
if(x==p[x]) return x;
else return p[x]=find(p[x]);
}
void un(int x,int y)
{
a=find(x);
b=find(y);
if(a==b)
return;
if(rank[a]>rank[b])
p[b]=a;
else
{
p[a]=b;
if(rank[a]==rank[b])
rank[b]++;
}
}
int main()
{
int i,sum;
while(cin>>m>>n&&(m||n))
{
for(i=0;i<m;i++)
{
p[i]=i;
rank[i]=0;
}
for(i=0;i<n;i++)
{
cin>>k;
if(k>=1)
cin>>f;
for(int j=1;j<k;j++)
{
cin>>t;//读入、合并
un(f,t);
}
}
sum=1;
for(i=1;i<m;i++)
{
if(find(i)==find(0))
sum++;
}
cout<<sum<<endl;
}
return 1;
}
这里的rank[i]标记这个i集合的深度
基本过程是:读入数据,判断~合并,最后找和0在同一个集合中的节点的个数~得解
poj2524跟此题类似
当然这都是并查集的基础题,下一道题是非常经典的~食物链