2016年 河南工业大学校赛 C题.魔法宝石

魔法宝石

时间限制: 2 秒  内存限制: 64 MB  |  提交: 582  解决: 187
  

题目描述

小s想要创造n种魔法宝石。小s可以用ai的魔力值创造一棵第i种魔法宝石,或是使用两个宝石合成另一种宝石(不消耗魔力值)。请你帮小s算出合成某种宝石的所需的最小花费。

输入

第一行为数据组数T(1≤T≤3)。
对于每组数据,首先一行为n,m(1≤n,m≤10^5)。分别表示魔法宝石种类数和合成魔法的数量。
之后一行n个数表示a1到an。(1≤ai≤10^9)。a_i表示合成第i种宝石所需的魔力值。
之后n行,每行三个数a,b,c(1≤a,b,cn),表示一个第a种宝石和第b种宝石,可以合成一个第c种宝石。

输出

每组数据输出一行n个数,其中第i个数表示合成第i种宝石的魔力值最小花费。

样例输入

1
3 1
1 1 10
1 2 3

样例输出

1 1 2
思路:由于宝石 可以由其他两种宝石 合成而来 , 所以可以通过合成宝石的方式 来使用更少的魔力 制造出宝石 ,
   注意 一个宝石可以由两个 子宝石 合成而来 , 而 子宝石也可能由 两个子宝石 合成而来 。。。。。
所以 只遍历 一遍 优化宝石合成所需要的 魔力 是不够的 , 而且也不确定需要 松弛多少次 ,
这个时候应该就能想到 spfa 算法了
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstring>

using namespace std ;

#define maxn 110000
#define LL long long
int num[maxn] ;
int sum[maxn] ;

int a , b , c ;
int T , n , m ;
struct node {
    int a , b , c ;
};
node edge[maxn] ;

void spfa() {
    bool flag = true ;
    while(flag) {
        flag = false ;
        for(int i=1 ; i<=m ; i++) {
            if(num[edge[i].c] > num[edge[i].a] + num[edge[i].b]) {
                flag = true ;
                num[edge[i].c] = num[edge[i].a] + num[edge[i].b] ;
            }
        }
    }
}

int main() {

    scanf("%d" , &T) ;
    while(T--) {
        scanf("%d %d" , &n , &m ) ;
        for(int i=1 ; i<=n ; i++) {
            scanf("%d" , &num[i]) ;
            sum[i] = num[i] ;
        }

        for(int i=1 ; i<=m ; i++) {
            scanf("%d %d %d" , &edge[i].a , &edge[i].b , &edge[i].c) ;

        }

        spfa() ; 
        
        for(int i=1 ; i<=n ; i++) {
            if(i == 1 ) {
                printf("%d" , num[i]) ;
            } else {
                printf(" %d" , num[i]) ;
            }
        }
        printf("
") ;
    }

    return 0 ;
}
原文地址:https://www.cnblogs.com/yi-ye-zhi-qiu/p/7878621.html