hdu-1863 暢通工程(kruskal算法+並查集)

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1863

kruskal算法思想:目標:得到最小生成樹。步驟:把邊分爲兩個集合,每次從集合中取出 權值最小的未成樹的邊 加入到成樹的集合裏,當有n-1條邊時得到最小生成樹。

hdu-1863 暢通工程(kruskal算法+並查集)

#include<cstdio>
#include<cstdlib>
#define MAXN 10000+10
using namespace std;


//par數組用於表示並查集 
int par[MAXN],Rank[MAXN];

//a結構體 表示每條邊 
typedef struct{
    int a,b,price;
}Node;
Node a[MAXN];

//用於qsort函數,返回值 a>b +,a<b -,a==b 0;還需要強制類型轉換,返回值爲int 
int cmp(const void*a,const void *b){
    return ((Node*)a)->price - ((Node*)b)->price;
} 

void Init(int n){
    for(int i=0;i<n;i++){
        Rank[i]=0;
        par[i]=i;//初始化把每個節點的父節點初始化爲自己 
    }
}

int find(int x){//找到編號爲x的點的父親節點 
    int root = x;
    while(root != par[root])root = par[root];//找到最父親的節點??如果兩個點互相死循環怎麼辦? 
    while(x != root){//如果最父親節點不是它自己,把它的父節點設爲最父親節點,然後繼續把它父親的父親節點設爲最父親節點,直到 全部父親節點都爲最父親節點 
        int t = par[x];
        par[x] = root;
        x = t;
    }
    return root;//返回最父親節點 
}

void unite(int x,int y){
    x = find(x);
    y = find(y);
    if(Rank[x]<Rank[y]){
        par[x]=y;
    }
    else{
        par[y]=x;
        if(Rank[x] == Rank[y]) Rank[x]++;
    }
}

//n爲邊的數量,m爲村莊的數量
int Kruskal(int n,int m){
    //nEdge是邊的編號,res是最小代價和 
    int nEdge = 0,res=0;
    //將邊按照權值從小到大排序
    qsort(a,n,sizeof(a[0]),cmp); //!!!注意,一定是某一個元素的大小,不能是a,a只是指針大小,如果遇到不是int,就會出錯 
    for(int i=0;i<n&&nEdge!=m-1;i++){
        //判斷當前這條邊的兩個端點是否屬於同一棵樹的並查集 
        //如果不在 就加到一起,然後算出當前最小代價和,指向編號爲下一個的邊 
        if(find(a[i].a)!=find(a[i].b)) {
            unite(a[i].a,a[i].b);
            res += a[i].price;
            nEdge++;
        }
    }
    //如果加入邊的數量小於m-1,則該無向圖不連通,等價於不存在最小生成樹
    if(nEdge < m-1) res = -1;
    return res; 
} 

int main(){
    int n,m,ans;
    while(scanf("%d%d",&n,&m)&&n!=0){
        Init(m);
        for(int i=0;i<n;i++){
            scanf("%d%d%d",&a[i].a,&a[i].b,&a[i].price);
            //將點編號變爲0~m-1
            a[i].a--;
            a[i].b--; 
        }
        ans = Kruskal(n,m);
        if(ans == -1)printf("?\n");
        else printf("%d\n",ans);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章