並查集——新手學習記錄

好吧,什麼垃圾並查集,並查集什麼的都是鐵憨憨<+__+>php

如今開始複習回憶:(新手,有錯誤望指正)數組

什麼叫作並查集,並查集就是一個集合問題,其實最主要的就是知道並查集是一個求解集合數目的問題,具體的操做方法有點飄。函數

或者這樣理解:——並查集經過一個一維數組來實現,其本質是維護一個森林。(好吧,我也不是很理解),個人理解就是經過一維數組來實現,子節點與父節點之間聯繫,而後查找集合個數。。。。。。。優化

好吧,不清楚,若是看了前面你很懵逼,那就全都忘了吧,,,spa

接下來纔是正餐:https://blog.51cto.com/ahalei/2348145code

直接上代碼:blog

題目是杭電的暢通工程:http://acm.hdu.edu.cn/showproblem.php?pid=1232遞歸

#include<stdio.h>
int fa[1001]={0};
void zore(int n)//未知量用n表示,初始化
{
    for(int i=1;i<=n;i++)
        fa[i]=i;
}

int find_father(int x)//返回老大,或者說是根節點
{
    if(fa[x]== x)
        return x;
    else{
        fa[x]=find_father(fa[x]);//優化路徑
        return fa[x];
    }
}

void unions(int n,int m)
{
    if(find_father(n)!=find_father(m))
        fa[find_father(m)]=find_father(n);
}

int main()
{
    int n,m;
    while(scanf("%d %d",&n,&m)&&n)
    {
        int sum=0;
        zore(n);
        while(m--)
        {
            int a,b;
            scanf("%d %d",&a,&b);
            unions(a,b);
        }
        for(int i=1;i<=n;i++)
        {
            if(fa[i]==i)
                sum++;
        }
        printf("%d\n",sum-1);
    }
    return 0;
}

如今咱們把代碼拆開來講:io

int main()
{
    int n,m;//題目中的n表明城市個數,m表明道路數
    while(scanf("%d %d",&n,&m)&&n)
    {
        int sum=0;//用來預裝須要修的路數
        zore(n);//調用初始化函數,來使咱們的一維數組初始化
        while(m--)//輸入m條路
        {
            int a,b;//a,b分別表明道路的起始城市的標號
            scanf("%d %d",&a,&b);
            unions(a,b);//合併有相鄰道路的城市,爲最後計算道路數作準備:好比最後若是隻有兩個集合,只須要修一條路;三個集合兩條路的思想。
        }
        for(int i=1;i<=n;i++)
        {
            if(fa[i]==i)//尋找到底有幾個獨立集合
sum++; } printf("%d\n",sum-1); } return 0; } 

 接下來:class

int fa[1001]={0};
void zore(int n)//初始化做用,這點很重要,由於這個操做爲咱們接下來的操做提供了數據
{
    for(int i=1;i<=n;i++)
        fa[i]=i;
}

 再接下來:

int find_father(int x)//這個very very重要
{  //做用是查找根結點,父節點...>若是你看過第一篇文章,你就把他理解成最大的BOOS就行了
    if(fa[x]== x)若是查找點本身就是本身的最大BOOS,則返回
        return x;
    else{
        fa[x]=find_father(fa[x]);//優化路徑,其實 是一個遞歸調用
        return fa[x];//優化事後改變了樹的結構,  子節點不少直接變成了根結點       
    }
}

  再接下來再:

void unions(int n,int m)
{
    if(find_father(n)!=find_father(m))//合併操做..>其實就是當兩我的的老大不一我的的時候,然而卻須要創建聯繫,好吧,這個時候兩我的就要開始幹架了,最直接的方法是
fa[find_father(m)]=find_father(n);//直接讓兩我的的老大來談話,讓一個老大認另外一我的的老大爲老大,此時他們就屬於同一個集合,此時就消除了集合間的隔離,或者說
//合併了兩個集合 }

 

void unions(int x,int y)
{
    int b1=find_father(n);//或者變成這樣,x市到y市之間有一條路,查詢x與y市的老大是誰
    int b2=find_father(m);
    if(b1!=b2)//判斷x與y市在不在一個集合
        fa[b1]=b2;//若是不在,合併
}
相關文章
相關標籤/搜索