并查集及其应用

           并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。

           并查集的操作:

                 1、查找某元素x所在集合

                         首先定义x的父节点为f(x),则查找x所在集合的操作即为查找x节点的祖先。

                                

          int find(int x)
         { 
               if(x != f[x])
                    f[x] = find(f[x]);//查找父节点为其本身的节点即为x节点所在集合的祖先
               return f[x];
          }
           

                2、合并两个元素x,y所在的集合

                              合并俩不相交集合很简单,用find(x),find(y)找到元素对应集合的父节点,将一个集合的父节点指向另一个集合的父节点即可

                      

          void Union(int x,int y)  
         {  
             x=Find_Set(x);  
             y=Find_Set(y);  
             if(x==y)  
                 return;  
             if (rank[x]>rank[y])  //rank[]指树的高度
             {  
                p[y]=x;  
                num[x]+=num[y]; //num[]表示集合x的元素个数 
             }   
             else  
             {  
                p[x]=y;  
                if (rank[x]=rank[y])  
                     rank[x]++;  
                num[y]+=num[x];  
              }  
         }  

                    应用:poj 1611

#include <iostream>
const int Max=30001;

int p[Max],rank[Max];
int num[Max];//元素个数

int Find_Set(int x)
{
	if (x!=p[x])
		p[x]=Find_Set(p[x]);
	return p[x];
}

void Union(int x,int y)
{
	x=Find_Set(x);
	y=Find_Set(y);
	if(x==y)
		return;
	if (rank[x]>rank[y])
	{
		p[y]=x;
		num[x]+=num[y];
	} 
	else
	{
		p[x]=y;
		if (rank[x]=rank[y])
			rank[x]++;
		num[y]+=num[x];
	}
}

int main()
{
	int i,j,k,n,m;
	int a,b;
	int s1,s2;
	while (true)
	{
		scanf("%d %d",&n,&m);
		if(n==0&&m==0)
			break;
		for (i=0;i<n;i++)
		{
			p[i]=i;
			rank[i]=0;
			num[i]=1;
		}
		for (i=0;i<m;i++)
		{
			scanf("%d",&k);
			scanf("%d",&a);
			for (j=1;j<k;j++)
			{
				scanf("%d",&b);
				s1=Find_Set(a);
				s2=Find_Set(b);
				Union(s1,s2);
				/*a=i;*/			
			}
		}
		i=Find_Set(0);
		printf("%d",num[i]);
	}
	return 0;
}

选自:http://cavenkaka.iteye.com/blog/1171373

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值