NYOJ-38 布线问题


布线问题

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 4
描述
南阳理工学院要进行用电线路改造,现在校长要求设计师设计出一种布线方式,该布线方式需要满足以下条件:
1、把所有的楼都供上电。
2、所用电线花费最少
输入
第一行是一个整数n表示有n组测试数据。(n<5)
每组测试数据的第一行是两个整数v,e.
v表示学校里楼的总个数(v<=500)
随后的e行里,每行有三个整数a,b,c表示a与b之间如果建铺设线路花费为c(c<=100)。(哪两栋楼间如果没有指明花费,则表示这两栋楼直接连通需要费用太大或者不可能连通)
随后的1行里,有v个整数,其中第i个数表示从第i号楼接线到外界供电设施所需要的费用。( 0<e<v*(v-1)/2 )
(楼的编号从1开始),由于安全问题,只能选择一个楼连接到外界供电设备。
数据保证至少存在一种方案满足要求。
输出
每组测试数据输出一个正整数,表示铺设满足校长要求的线路的最小花费。
样例输入
1
4 6
1 2 10
2 3 10
3 1 10
1 4 1
2 4 1
3 4 1
1 3 5 6
样例输出
4

思路分析:考查最小生成树,我使用的kruskal,最后求出最小生成树还要再额外加一个最小的供电费用,就是题中所说的第i号楼接线到外界供电设施的最小费用。


#include <cstdio>
#include <algorithm>
#include <vector>

#define MAX 500 + 10
#define INF 0x3fffffff

using namespace std;

typedef struct {
    int a;
    int b;
    int l;
} Edge;

vector<Edge> edge;
int father[MAX];
vector<int> cost;

void initSet() {
    for( int i = 0; i < MAX; i++ ) {
        father[i] = i;
    }
}

int cmp( Edge a, Edge b ) {
    return a.l < b.l ? 1 : 0;
}

int findFather( int x ) {
    int a = x;
    while( x != father[x] ) {
        x = father[x];
    }

    while( a != father[a] ) {
        int z = a;
        a = father[a];
        father[z] = x;
    }

    return x;
}

void Union( int a, int b ) {
    int faA = findFather( a );
    int faB = findFather( b );

    father[faA] = faB;
}

int kruskal( int n ) {
    sort( edge.begin(), edge.end(), cmp );

    int cnt = 0;
    int MST = 0;
    for( int i = 0; i < edge.size(); i++ ) {
        int faA = findFather( edge[i].a );
        int faB = findFather( edge[i].b );

        if( faA != faB ) {
            Union( edge[i].a, edge[i].b );
            MST += edge[i].l;
            cnt++;
        }
    }

    if( cnt == n - 1 ) return MST;
}

int main() {
    int T;

    scanf( "%d", &T );

    while( T-- ) {
        initSet();
        edge.clear();
        cost.clear();

        int n, m;
        scanf( "%d%d", &n, &m );

        int a, b, l;
        Edge e;
        for( int i = 0; i < m; i++ ) {
            scanf( "%d%d%d", &a, &b, &l );
            e.a = a - 1;
            e.b = b - 1;
            e.l = l;
            edge.push_back( e );
        }

        int c;
        for( int i = 0; i < n; i++ ) {
            scanf( "%d", &c );
            cost.push_back( c );
        }

        int MST = kruskal( n );

        sort( cost.begin(), cost.end() );

        MST += cost[0];

        printf( "%d\n", MST );

    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值