题目
July 8, 2021 · View on GitHub
一颗树有 n 个节点,这些节点被标号为:1,2,3…n,每个节点 i 都有一个权值 A[i]。
现在要把这棵树的节点全部染色,染色的规则是:
根节点 R 可以随时被染色;对于其他节点,在被染色之前它的父亲节点必须已经染上了色。
每次染色的代价为 T×A[i],其中 T 代表当前是第几次染色。
求把这棵树染色的最小总代价。
输入格式 第一行包含两个整数 n 和 R,分别代表树的节点数以及根节点的序号。
第二行包含 n 个整数,代表所有节点的权值,第 i 个数即为第 i 个节点的权值 A[i]。
接下来 n−1 行,每行包含两个整数 a 和 b,代表两个节点的序号,两节点满足关系: a 节点是 b 节点的父节点。
除根节点外的其他 n−1 个节点的父节点和它们本身会在这 n−1 行中表示出来。
同一行内的数用空格隔开。
输出格式 输出一个整数,代表把这棵树染色的最小总代价。
数据范围
1≤n≤1000,
1≤A[i]≤1000
输入样例:
5 1
1 2 1 2 4
1 2
1 3
2 4
3 5
输出样例:
33
参考答案
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1010;
int n, root;
struct Node
{
int p, s, v;
double avg;
}nodes[N];
int find()
{
double avg = 0;
int res = -1;
for (int i = 1; i <= n; i ++ )
if (i != root && nodes[i].avg > avg)
{
avg = nodes[i].avg;
res = i;
}
return res;
}
int main()
{
cin >> n >> root;
int ans = 0;
for (int i = 1; i <= n; i ++ )
{
cin >> nodes[i].v;
nodes[i].avg = nodes[i].v;
nodes[i].s = 1;
ans += nodes[i].v;
}
for (int i = 0; i < n - 1; i ++ )
{
int a, b;
cin >> a >> b;
nodes[b].p = a;
}
for (int i = 0; i < n - 1; i ++ )
{
int p = find();
int father = nodes[p].p;
ans += nodes[p].v * nodes[father].s;
nodes[p].avg = -1;
for (int j = 1; j <= n; j ++ )
if (nodes[j].p == p)
nodes[j].p = father;
nodes[father].v += nodes[p].v;
nodes[father].s += nodes[p].s;
nodes[father].avg = (double)nodes[father].v / nodes[father].s;
}
cout << ans << endl;
return 0;
}