本文主要是介绍MZ Training 2014 #8 F题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
这个题啊。。。先上题吧。
[Description]
有n个点,m条边,现在要用这些来建立一颗以1号点为根的圣诞树
对于每一个点有一个点权w, 每条边也有一个边权c
对于一棵树的代价,我们这样计算(具体可以看看样例解释):
代价=每个点的代价和
一个点的代价=这个点及它的所有后代节点点权之和乘以指向它的边的边权。
[Input]
第一行一个整数T,表示T组数据
对于每组数据,第一行两个整数n和m
第二行n个整数wi,每个点的点权
接下来m行,每行三个整数a b c,表示a和b之间有一条边权为c的无向边
[Output]
对于每组数据输出一行,即最小的代价Total
如果不能组成一棵树,则输出 “ No Answer ”
[Sample Input]
2
2 1
1 1
1 2 15
7 7
200 10 20 30 40 50 60
1 2 1
2 3 3
2 4 2
3 5 4
3 7 2
3 6 3
1 5 9
[Sample Output]
15
1210
[Hint]
0 <= n, m <= 50000
所有的数都小于216
对于样例2,我们不用1 5 9这一条边,那么建出来的树如图所示
其代价计算
1号点:(200 + 10 + 20 + 30 + 40 + 50 + 60) * 0 = 0
2号点:(10 + 20 + 30 + 40 + 50 + 60) * 1 = 210
3号点:(20 + 40 + 50 + 60) * 3 = 510
4号点:30 * 2 = 60
5号点:40 * 4 = 160
6号点:60 * 2 = 120
7号点:50 * 3 = 150
Total = 0 + 210 + 510 + 60 + 160 + 120 + 150 = 1210
那么这个问题是可以简化的。对于指向某个节点的一条边,它的后代必然会参与计算这条边。所以某个点的点权就会被从根(1)到它的所有边计算一次。为什么不以每个子节点为计算单位呢?
这TM不就是对每个点求最短路吗?
好了,答案出来了,就是这个。
n为点的个数;dis[i]为1到这个点的最短路;w[i]为这个点的点权。
注意:
①:判断无解(出现不连通)
②:最坏情况答案 49999*65536=3276734464,所以dis[]数组要开long long;
③:初值必须够大,但要注意:不能用memset,因为它不能赋超int的初值;
也不能这样写:for(int i=1;i<=n;i++) dis[i]=4000000000;
而要这样写:for(int i=1;i<=n;i++) dis[i]=4000000000LL;
加的“LL”表示这个常量是long long 的;
④:人品要好!
这篇关于MZ Training 2014 #8 F题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!