给树染色(贪心+树上操作)

题目描述: 一颗树有 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 0 0

输出样例:
33

这道题北大yxc学长讲的非常好,下面是他的讲解
给树染色(贪心+树上操作)
文章图片

AC代码:
#include #include #include #include #include #include #include #include #include const int INF = 0x3f3f3f3f; using namespace std; typedef long long ll; typedef double ld; 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>a>>b; nodes[b].p=a; } for (int i=0; i

    推荐阅读