并查集

并查集:

      并查集说的是将一些元素分为几个集合,每个集合各自有自己的共同特点,当然便于查询,每个集合都必须有各自的标志(编号),我们可以通过这个标志来查询集合里的元素,判断元素是否属于这个集合,总共分为了多少个集合。于是,我们选择了树形结构存每个集合的元素。某棵树的根相当于这个集合的标志。有几棵树就有几个集合。判断两个元素是否属于同一个集合,就看它们的根是否一致(用递归可查询它们的根)。

基本操作代码:

初始化:
void init()
{
    	for(int i=1;i<=n;i++)
	{
		root[i]=i;//初始时,每个元素都是一颗以自己为根的树
		rank[i]=0;//树的高度
	}
}
 
找根:
int find_root(int v)
{
	if(root[v] != v)
	{
		root[v]=find_root(root[v])//路径压缩,root[v]经过递归之后最终就会是此时v所在的树的根
	}
	return  root[v];
}

合并:
void unite(int x,int y)
{
	int rx=find_root(x);
	int ry=find_root(y);
	if(rx==ry) return;//以前就属于同一棵树
	if(rank[rx]>rank[ry])
	{
		root[ry]=rx;//将根为ry的那棵树变为根为rx的子树,由于rank[ry]+1<=rank[rx],所以rank[rx]不需要变;
     	}
	else if(rank[rx]==rank[ry])
	{
		root[ry]=rx;
		rank[rx]++;
	}
	else
	{
		root[rx]=ry;
	}
}

学并查集的收获:

给集合标号;找“根”的方法;路径压缩的方法;

注意事项:

经过一系列的合并(unite)操作之后,root[i]还不一定是i所在树的根,可能只是这颗树下的子树的根,所以要求它的根还需find_root(i)

 

例题:

HDU1829 A Bug’s life

题意:有一些小虫子,虫子里面可能有同性恋,一位博士通过观察它们的交配情况,来判断是否有同性恋,若能判断出来有,则输出Suspicious bugs found! 否则输出No suspicious bugs found!

分析:这是一道经典的并查集,由于题目告诉了你它们的交配情况,我们以他们的性别为划分集合的依据,则互相交配的虫子分属不同的集合,即它与和它交配的虫子的反面在一个集合内。

 

代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

int b_f[5000];
void init(int n)
{
    for(int i=1;i<=n;i++)
    {
        b_f[i]=i;
    }
}
int f_root(int a)
{
    if(b_f[a]!=a)
        b_f[a]=f_root(b_f[a]);
    return b_f[a];


}
void Union(int x,int y)
{
    int fx=f_root(x);
    int fy=f_root(y);
    b_f[fx]=fy;
}
int main()
{
    int cnt;
    int m,n;
   scanf("%d",&cnt);
    int co=0;
    while(scanf("%d %d",&m,&n))
    {
        if(cnt==0) break;
        cnt--;
        co++;
        int a,b;
        bool ju=true;
        init(2*m);
        for(int i=0;i<n;i++)
        {
            scanf("%d %d",&a,&b);
            //cin>>a>>b;
            if(!ju) continue;
            if(f_root(a)!=f_root(b))
            {
                Union(a,b+m);//a与b的反面放在同一个集合中
                Union(b,a+m);
            }
            else
                ju=false;
        }
        if(!ju)
            printf("Scenario #%d:\nSuspicious bugs found!\n\n",co);
        else
            printf("Scenario #%d:\nNo suspicious bugs found!\n\n",co);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章