2013年1月4日 星期五

[ZJ] a129. 最小生成樹


內容 : 
給你一個加權的無向圖(weighted undirected graph),請問這個圖的最小生成樹(minimum spanning tree)的權重和為多少?
輸入說明 :
輸入可能包含多筆測試資料,以EOF作為結束。 
每筆測試資料的第一列有兩個整數n,m(1<=n<=100,000;0<=m<=200,000),代表該圖的點數和邊數。
頂點的編號從0到n-1。
接下來有m列,每列用三個整數i,j,c(0<=i,j<n;c為int可儲存的非負整數)描述一條邊,i,j為兩個端點的編號,c為其權重。 
輸出說明 :
對於每筆測試資料,請輸出最小生成樹的權重和。如果圖不連通,請輸出-1。
範例輸入 :help
3 31 2 52 3 53 1 104 21 2 52 3 5
範例輸出 :
10-1
提示 :
overflow..?
出處 :
(管理:shik)

作法: 并查集

/**********************************************************************************/
/*  Problem: a129 "最小生成樹" from                                          */
/*  Language: C                                                                   */
/*  Result: AC (876ms, 10432KB) on ZeroJudge                                      */
/*  Author: morris1028 at 2011-05-14 20:44:26                                     */
/**********************************************************************************/


#include<stdio.h>
#include<stdlib.h>
int Parent[100001], Rank[100001];
int a, N, M;
void MakeSet(int N) {
    for(a=0;a<=N;a++)
        Parent[a] = a, Rank[a] = 1;
}
int FindSet(int x) {
    if(x!=Parent[x])
        Parent[x] = FindSet(Parent[x]);
    return Parent[x];
}
void Link(int x, int y) {
    if(Rank[x]>Rank[y])
            Parent[y] = x, Rank[x] += Rank[y];
    else
            Parent[x] = y, Rank[y] += Rank[x];
}
int Union(int x, int y) {
    x = FindSet(x), y = FindSet(y);
    if(x != y) {
        Link(x, y);
        return 1;
    }
    return 0;
}
int Input() { 
    char cha; 
    unsigned int x=0; 
    while(cha=getchar()) 
        if(cha!=' '&&cha!='\n' || cha==EOF) break; 
    if(cha==-1) return -1;
    x=cha-48; 
    while(cha=getchar()) { 
        if(cha==' '||cha=='\n') break; 
        x=x*10+cha-48; 
    } 
    return x; 
}
struct Axis{
    int x, y, s;
}Data[400001], X[400001];
void Merge(int, int, int);
void MergeSort(int, int);
main() {
    int T, a, flag;
    long long Ans;
    while(scanf("%d %d",&N, &M) == 2) {
        for(a=0;a<M;a++) {
            Data[a].x = Input(), Data[a].y = Input(), Data[a].s = Input();
            Data[M+a].x = Data[a].x,
            Data[M+a].y = Data[a].y,
            Data[M+a].s = Data[a].s;
        }
        M *= 2;
        MergeSort(0, M-1), MakeSet(N), Ans = 0, flag = 0;
       
        for(a=0;a<M && flag < N;a++)
            if(Union (Data[a].x, Data[a].y) == 1) {
                Ans += Data[a].s, flag ++;
            }
        printf("%lld\n",(flag == N-1)? Ans : -1);
    }
    return 0;
}
void MergeSort(int l, int h) {
    if(l < h) {
        int m=(l+h)/2;
        MergeSort(l  ,m);
        MergeSort(m+1,h);
        Merge(l,m,h);
    }
}
void Merge(int l, int m, int h) {
    int In1=l, In2=m+1;
    int a, b, Top=0;
    while(In1<=m && In2<=h)
        if((Data[In1].s < Data[In2].s))
             X[Top++]=Data[In1++];
       else  X[Top++]=Data[In2++];
    while(In1<=m)   X[Top++]=Data[In1++];
    while(In2<=h)   X[Top++]=Data[In2++];
    for(a=0,b=l;a<Top;a++,b++)
        Data[b]=X[a];
}

沒有留言:

張貼留言