andre_joy

导航

hdu 1863

地址:http://acm.hdu.edu.cn/showproblem.php?pid=1863

题意:中文。。。

mark:继续看题解。。神奇的最小生成树+并查集,算法名字叫Kruskal。听起来很高深的样子,但是算法理解起来不难,就是遇到这类型的题目,首先存放的是每条边的起点,终     点和权值,然后将所有边按权值的升序排序,然后从最小权值开始查找,用到并查集的方法,只须修改一下并查集里面merge函数,当发现当前边的起点和终点已经可以直接     或间接连在一起的时候,就不用管它,否则就将这两个点通过当前边连接起来,最后判断一下是否所有点都已经连接起来。

代码:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>

using namespace std;

typedef long long LL;

typedef struct
{
    int u,v,w;
}ss;

ss s[110];
int tt[110];
int n,m;

int cmp(const void *a, const void *b)
{
    return (*(ss *)a).w - (*(ss *)b).w;
}

int find(int a)
{
    while(a != tt[a]) a = tt[a];
    return a;
}

int merge(int a, int b)
{
    a = find(a);
    b = find(b);
    if(a != b)
    {
        tt[a] = b;
        return 1;
    }
    return 0;
}

int main(int argc, char **argv)
{
    int i,j,k;
    while(cin >> n >> m)
    {
        if(!n) break;
        for(i = 0; i < n; i++)
            cin >> s[i].u >> s[i].v >> s[i].w;
        qsort(s, n, sizeof(ss), cmp);
        for(i = 1; i <= m; i++)
            tt[i] = i;
        int sum = 0;
        for(i = 0; i < n; i++)
            if(merge(s[i].u, s[i].v))
                sum += s[i].w;
        int cnt = 0;
        for(i = 1; i <= m; i++)
            if(tt[i] == i) cnt++;
        if(cnt == 1) cout << sum << endl;
        else cout << '?' << endl;
    }
    return 0;
}

 

posted on 2013-06-01 20:33  andre_joy  阅读(370)  评论(0编辑  收藏  举报