nyoj38布线问题

布线问题

时间限制: 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

1)典型的最小生成树问题;有n个点,连接n - 1条线,使的权值之和最小, 裸prime算法

2)这种问题还有另一种问法,就是n个点,连接n - 1条线,使的权值之和最大(常见的是:奸商为了挣钱,要求路线话费最大, 从而其挣得钱就越多!太贱了);这种情况就是第一种情况的变化,稍微变化一下可以求解,输入边的时候取相反数,那么最后求解的最小即是负值最小,其绝对值也就是为整数的最大。


/*************************************************************************
> File Name: mst.c
> Author: xzl
> Mail:xiaolongqdu@gmail.com 
> Created Time: 2013年11月19日 星期二 09时50分51秒
 ************************************************************************/

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
#define Max_len 600
#define MAX 1000000

using namespace std;
typedef struct node{
    int var;
    int weight;
}node;
int v, e;
int Min;
int mincost[Max_len];
vector<node>map[Max_len];

void prim(int var);

int main(){
    
    int n, i;
    int a, b, c, temp;
    node no, no1;

    scanf("%d", &n);
    while(n--){
        memset(mincost, 0, sizeof(mincost));
        scanf("%d %d", &v, &e);
        for(i = 0; i < e; i++){
            scanf("%d %d %d", &a, &b, &c);
            no.var = b; no.weight = c;
            no1.var = a; no1.weight = c;
            map[a].push_back(no);
            map[b].push_back(no1);
        }
        scanf("%d", &Min);
        for(i = 1; i < v; i++){
            scanf("%d", &temp);
            if(Min > temp){
                Min = temp;
            }
        }
        prim(1);
        for(i = 1; i <= v; i++){
            map[i].clear();
        }
    } 
}

void prim(int var){
    
    int i;
    int intree[Max_len] = {0};
    int var_temp, wei, num, cost;

    for(i = 1; i <= v; i++){
        mincost[i] = MAX;
    }
    
    mincost[var] = 0;
    while(!intree[var]){
        intree[var] = 1;
        for(i = 0; i < map[var].size(); i++){
            var_temp = map[var][i].var;
            wei = map[var][i].weight;
            if(wei < mincost[var_temp] && !intree[var_temp]){
                mincost[var_temp] = wei;
            }
        }
        var = 1;
        num = MAX;
        for(i = 1; i <= v; i++){
            if(!intree[i] && mincost[i] < num){
                num = mincost[i];
                var = i;
            }
        }
    }
    cost = Min;
    for(i = 1; i <= v; i++){
        cost += mincost[i];
    }
    printf("%d\n", cost);
}

最小生成树,是图论中最基本的了,不会的筒子们,还等神马!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值