並查集

並查集:

      並查集說的是將一些元素分爲幾個集合,每個集合各自有自己的共同特點,當然便於查詢,每個集合都必須有各自的標誌(編號),我們可以通過這個標誌來查詢集合裏的元素,判斷元素是否屬於這個集合,總共分爲了多少個集合。於是,我們選擇了樹形結構存每個集合的元素。某棵樹的根相當於這個集合的標誌。有幾棵樹就有幾個集合。判斷兩個元素是否屬於同一個集合,就看它們的根是否一致(用遞歸可查詢它們的根)。

基本操作代碼:

初始化:
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;
}


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