标签:贪心 desc ++ 整理 mes 实时 空格 题解 cin
一颗树有 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 行中表示出来。
同一行内的数用空格隔开。
5 1 1 2 1 2 4 1 2 1 3 2 4 3 5 0 0
33
#include <iostream>
#include <cstdio>
#define N 1005
using namespace std;
struct A {int sum, size, fat; double avg;} a[N];
int n, root, ans;
int find()
{
int pos; double res = -1;
for(int i = 1; i <= n; i++)
if(i != root && a[i].avg > res)
res = a[i].avg, pos = i;
return pos;
}
int main()
{
cin >> n >> root;
for(int i = 1; i <= n; i++)
{
cin >> a[i].sum;
a[i].size = 1;
a[i].avg = a[i].sum;
ans += a[i].sum;
}
for(int i = 1; i < n; i++)
{
int u, v;
cin >> u >> v;
a[v].fat = u;
}
for(int i = 1; i < n; i++)
{
int p = find(), father = a[p].fat;
ans += a[father].size * a[p].sum;
a[father].sum += a[p].sum;
a[father].size += a[p].size;
a[father].avg = (double)a[father].sum / (double)a[father].size;
a[p].avg = -1;
for(int j = 1; j <= n; j++)
if(a[j].fat == p) a[j].fat = father;
}
cout << ans;
return 0;
}
标签:贪心 desc ++ 整理 mes 实时 空格 题解 cin
原文地址:https://www.cnblogs.com/BigYellowDog/p/11296812.html