Light OJ 1029- Civil and Evil Engineer (图论-最小生成树)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1029

题目大意:一个发电站,给n座房子供电, 任意房子之间有电线直接或者间接相连接, 现在想知道需要连接这些房子花费的平均电线长度。平均电线长度 = (最长电线长度 + 最短电线长度)/ 2;

解题思路:裸的最小生成树

代码如下:

#include <bits/stdc++.h>
using namespace std;
const int N = 1003;
struct edge
{
    int s, t, l;
    edge() {}
    edge(int s, int t, int l):s(s), t(t), l(l) {}
};
vector<edge>vec;
int par[N], Rank[N];
int n;

void init()
{
    for(int i=0; i<=n; ++ i)
        par[i] = i, Rank[i] = 0;
}

int Find(int x)
{
    if(par[x] == x)
        return x;
    else
        return par[x] = Find(par[x]);
}

void unite(int x, int y)
{
    x = Find(x), y = Find(y);
    if(x == y)
        return ;

    if(Rank[x] < Rank[y])
        par[x] = y;
    else
    {
        par[y] = x;
        if(Rank[x] == Rank[y])
            Rank[x] ++;
    }
}

bool same(int x, int y)
{
    return Find(x) == Find(y);
}

bool cmp(const edge &a, const edge &b)
{
    return a.l < b.l;
}

bool Cmp(const edge &a, const edge &b)
{
    return a.l > b.l;
}

int kruskal(int m)
{
    init();
    if(m == 1)
        sort(vec.begin(), vec.end(), cmp);
    else
        sort(vec.begin(), vec.end(), Cmp);
    int res = 0;
    for(int i=0; i<vec.size(); ++ i)
    {
        edge e = vec[i];
        if(!same(e.s, e.t))
        {
            unite(e.s, e.t);
            res += e.l;
        }
    }
    return res;
}

void solve(int cases)
{
    scanf("%d", &n);
    vec.clear();
    while(1)
    {
        int s, t, l;
        scanf("%d%d%d", &s, &t, &l);
        if((s || t || l) == false)
            break;
        vec.push_back(edge(s, t, l));
    }

    int ans = 0;
    ans += kruskal(1);
    ans += kruskal(2);
    if(ans & 1)
        printf("Case %d: %d/%d\n", cases, ans, 2);
    else
        printf("Case %d: %d\n", cases, ans/2);

}

int main()
{
    int t;
    scanf("%d", &t);
    for(int i=1; i<=t; ++ i)
        solve(i);
    return 0;
}
View Code

 

posted @ 2016-11-06 12:32  aiterator  阅读(180)  评论(0编辑  收藏  举报