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 }