bzoj 2197: [Usaco2011 Mar]Tree Decoration

  树形dp。。f[i]表示处理完以i为根的子树的最小时间。

  因为一个点上可以挂无数个,所以在点i上挂东西的单位花费就是i所在子树里的最小单位花费。。

  所以每次求f[i]只要使子树里的数量都满足要求就好了。。i的祖先还要更多的话随时可以选某个节点多挂一些。。

  f[i]=sum{f[j]}+mincost[i]*max(need[i]-sum{need[j]},0)。。(j是i的儿子,mincost[i]表示子树i里的最小花费,need[i]表示i这颗子树需要的最少数量)

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #define ll long long
 5 using namespace std;
 6 const int maxn=100013;
 7 struct zs{
 8     int too,pre;
 9 }e[maxn];
10 int last[maxn],mn[maxn],tot;
11 int i,j,k,n,m,a;
12 ll f[maxn],need[maxn];
13 int ra;char rx;
14 inline int read(){
15     rx=getchar();ra=0;
16     while(rx<'0'||rx>'9')rx=getchar();
17     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
18 }
19 void dfs(int x){
20     int i,to;ll sum=0;
21     for(i=last[x],to=e[i].too;i;mn[x]=mn[x]>mn[to]?mn[to]:mn[x],sum+=need[to],f[x]+=f[to],i=e[i].pre,to=e[i].too)dfs(to);
22     if(sum>=need[x])need[x]=sum;else f[x]+=(need[x]-sum)*(ll)mn[x];
23 }
24 int main(){
25     n=read();for(rx=getchar();rx!='-';rx=getchar());rx=getchar();
26     need[1]=read();mn[1]=read();
27     for(i=2;i<=n;i++)a=read(),e[i].pre=last[a],last[a]=e[i].too=i,need[i]=read(),mn[i]=read();
28     dfs(1);
29     printf("%lld\n",f[1]);
30     return 0;
31 }
View Code

相关文章: