1. 程式人生 > >Kruskal演算法(題目還是:還是暢通工程)

Kruskal演算法(題目還是:還是暢通工程)

那還是先把題目丟出來,是HDU上的一道題

 

暢通工程

 

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 27972    Accepted Submission(s): 12279


 

Problem Description

 

省政府“暢通工程”的目標是使全省任何兩個村莊間都可以實現公路交通(但不一定有直接的公路相連,只要能間接通過公路可達即可)。經過調查評估,得到的統計表中列出了有可能建設公路的若干條道路的成本。現請你編寫程式,計算出全省暢通需要的最低成本。

 

 

 

 

 

Input

 

測試輸入包含若干測試用例。每個測試用例的第1行給出評估的道路條數 N、村莊數目M ( < 100 );隨後的 N
行對應村莊間道路的成本,每行給出一對正整數,分別是兩個村莊的編號,以及此兩村莊間道路的成本(也是正整數)。為簡單起見,村莊從1到M編號。當N為0時,全部輸入結束,相應的結果不要輸出。

 

 

 

 

 

Output

 

對每個測試用例,在1行裡輸出全省暢通需要的最低成本。若統計資料不足以保證暢通,則輸出“?”。

 

 

 

 

 

Sample Input

 

3 3 1 2 1 1 3 2 2 3 4 1 3 2 3 2 0 100

 

 

 

Sample Output

 

3 ?

 

克魯斯卡爾演算法還是通過區域性貪心來求得全域性貪心的演算法,即每次都找到兩點之間最短的那條邊,就可以了。但是要用到並查集QAQ

 

#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
using namespace std;

struct node
{
    int u;
    int v;
    int w;
}edge[120];

int cmp(node A, node B)
{
    if(A.w < B.w) return 1;
    else return 0;
}

//定義父節點 
int fa[120];

int find(int x)
{
    int p =fa[x];
    while(p != fa[p]) p =fa[p];
    return p;
}

int main()
{
    int n, m;//道路條數n 村莊個數m
    
    //輸入 
    while(cin >> n >> m && n != 0 && m != 0)
    {
        //初始化,每個節點的父節點是其本身 
        for(int i = 1; i <= m; i++)
        {
            fa[i] = i;
        }
        
        for(int i = 0; i < n; i++)
        {
            cout<<edge[i].u<<edge[i].v<<edge[i].w<<endl;
        }
        sort(edge,edge + n,cmp);
        int sum = 0;//總路程
        int count = 0;//計數 
        for(int i = 0; i < n; i++)
        {
            int fx = find(edge[i].u);
            int fy = find(edge[i].v);
            if(fx != fy)
            {
                fa[fx] = fy;
                sum += edge[i].w;
                count++;
            }
        }
        if(count == M-1) cout<<sum<<endl;
        else cout<<"?"<<endl;
    }
    return 0;
}