並查集解決最優灌溉問題(最小生成樹問題)

以下都是個人理解,解釋別人寫好的代碼,隨便寫寫
1.什麼是並查集
是一種數據結構,其實也就是一種樹結構
把i節點的父節點保存在array[i]數組裏,根節點的父節點爲自身。
對於這種數據結構可以實現的功能有兩個
(1)查找一個節點的根節點,通過數組裏保存的父節點一層一層向上查找,知道找到一個節點的父節點是自己,那這個節點就是根節點了。
(2)判斷兩個節點是否屬於一個樹,找到這兩個節點的根節點進行比較,如果根節點相同,這兩個節點就屬於一個樹,如果不相同,就不屬於一個樹。
(3)把兩個樹合併,在功能(2)中如果判斷出兩個節點不屬於一個樹,想要把這兩個樹合併,就把其中一個節點的根節點的父節點從自身變更爲另一個節點的根節點,就可以實現兩個樹的合併,即並集。
2.最優灌溉問題
本質都一樣,求最小生成樹
3.代碼實現

# include <iostream>
# include <algorithm>
using namespace std;
struct vex  //水渠結構體數組
{
    int i,j,a;
};
int node[100];   //並查集的節點數組,值代表當前節點的父節點
bool comp(vex a,vex b) //自定義比較函數
{
    return a.a<b.a;
}
int find( int a) //並查集的查詢算法
{
    return node[a] == a ? a : find(node[a]);
}
int main()
{
    int m,n;//m代表麥田數量   n代表可建立的水渠數量
    scanf("%d %d",&m,&n);
    vex v[100];
    for(int i =0;i<n;i++)
    {
        scanf("%d %d %d",&v[i].i,&v[i].j,&v[i].a); //輸入每一條可建造的水渠的數據
    }
    for(int i=0;i<m;i++)
    {
        node[i] = i;  //初始化每個麥田所在樹結構的根節點爲自身
    }
    sort(v,v+m,comp);//先根據每條水渠的花費對水渠結構體數組進行排序 從小到大
    int num = 0;//  記錄最終花費
    int bian = 0; //記錄當前建造的水渠數量
    for(int i = 0;bian < m-1;i++) 
    {
        if(find(v[i].i) != find(v[i].j)) //如果父節點不相同,說明該兩個麥田不在一個樹中,則把該兩個節點合併到一個樹中,即使父節點相同,
        {                                                                       //建造這兩個麥田之間的水渠,因爲已經過排序,所以是當前花費最少的一個水渠   
            num+=v[i].a; //增加花費                                    如果兩個麥田的根節點相同,說明這兩個麥田以通水田,不需要再建立,則跳過該條水渠的建立
            bian++; //增加水渠數量
            node[v[i].j] = find(v[i].i); //使v[j].j節點的根節點 = v[i].i節點的根節點
            printf("%d --- %d     %d\n",v[i].i,v[i].j,v[i].a);  //打印出當前建造的水渠的起始於結束節點與花費
        }
    }
    printf("最少花費:   %d",num);
    return 0;
}

這裏面用到了sort函數,是algorithm庫裏自帶的一個排序函數。

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