并查集基础~poj1611

本文介绍了并查集的基本概念及其实现方法,通过具体的代码示例展示了如何使用并查集解决实际问题,并讨论了其优化技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://poj.org/problem?id=1611

并查集的基本思想就是:它的每个元素开始都属于各自的一个集合,查找两个元素所属的集合是否属于同一个集合,如果不是则合并~   

    实现方法很简单~ 用树来实现~所有属于同一集合的元素属于同一棵树,

这样我们就可以用数根来表示一个集合,要找到某个元素属于哪个集合
,只要找到这个元素所在的树的树根;要合并两个集合,只要合并两棵树。一般比
较方便的方法是用父亲数组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跟此题类似

当然这都是并查集的基础题,下一道题是非常经典的~食物链

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值