题解 P3018 【[USACO11MAR]树装饰Tree Decoration】
可以用dfs递归找一找
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int SN = 100000 + 10;
LL f[SN], t[SN], c[SN], now[SN], head[SN];
LL n, ans, que[SN], num, root;
bool vis[SN];
struct Edge {
int from,to,next;
}E[SN<<1];
void dfs(int u) {
vis[u] = 1;
for(int i = head[u]; i ;i = E[i].next) {
if(vis[E[i].to]) continue;
dfs(E[i].to);
c[u] = min(c[u] , c[E[i].to]); //小贪心,更新树中最小的花费
now[u] += now[E[i].to]; //更新一下当前以i为节点的子树中购买的个数
}
if(now[u] < t[u]) {
ans += (t[u]-now[u]) * c[u]; //如果不够,接着买
now[u] = t[u];
}
}
void Add(int u,int v) {
E[++num].from = u;
E[num].to = v;
E[num].next = head[u];
head[u] = num;
}
int main() {
scanf("%lld",&n);
for(int i = 1; i <= n; i++) {
scanf("%lld%lld%lld",&f[i],&t[i],&c[i]);
if(f[i] != -1)
Add(i,f[i]),Add(f[i],i); //加无向边
else root = i;
}
dfs(root);
printf("%lld\n",ans);
return 0;
}