BZOJ_2197
如果子树中有某个节点不符合要求,即便根再怎么符合要求都是没有任何意义的,因此要优先安排好子树中节点使其符合要求,再考虑根节点。对于任何一棵子树来讲,如果所有孩子选择的点的总和仍然不足根的C值的话,那么就还要在孩子中选出一些节点,而且如果要选那么必然应该选T最小的点。
#include<stdio.h> #include<string.h> #include<algorithm> #define MAXD 100010 #define MAXM 100010 typedef long long LL; int N, first[MAXD], e, next[MAXM], v[MAXM], c[MAXD], t[MAXD]; LL ANS, size[MAXD]; void add(int x, int y) { v[e] = y; next[e] = first[x], first[x] = e ++; } void init() { int p; memset(first, -1, sizeof(first[0]) * (N + 1)), e = 0; for(int i = 1; i <= N; i ++) { scanf("%d%d%d", &p, &c[i], &t[i]); if(p != -1) add(p, i); } } int dfs(int cur) { int min = t[cur]; size[cur] = 0; for(int i = first[cur]; i != -1; i = next[i]) { min = std::min(min, dfs(v[i])); size[cur] += size[v[i]]; } if(size[cur] < c[cur]) ANS += (c[cur] - size[cur]) * min, size[cur] = c[cur]; return min; } void solve() { ANS = 0; dfs(1); printf("%lld\n", ANS); } int main() { while(scanf("%d", &N) == 1) { init(); solve(); } return 0; }