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;
}