题目链接在这里:Problem - C - Codeforces
树形DP很重要的一点就是要倒着做,就是自底向上。当时正着做想了半天没想出来硬是没想着能倒着搞…… 树形DP因为要考虑完孩子节点再考虑当前节点,所以要先遍历再操作。
对于每一个点都有两个限制条件,一个是到当前点能抓到的人数一定>=孩子节点能抓到的人数。另一个是当前子树人数之和平均分到每一个叶子结点上取整(这个不一定能做到,但是如果做不到,那出来的答案一定比上一个限制条件小)
自顶向下讨论是从繁到简的讨论,非常的阴间,我们的讨论应该是从简至繁,从最简单的情况一步步推到最复杂的情况,所以应该从后向前讨论。
下次如果卡住了从前向后讨论的时候可以想着从后向前讨论。
1 #include "bits/stdc++.h" 2 using namespace std; 3 const int MAX=2e5+5; 4 typedef long long LL; 5 LL n; 6 LL tot,head[MAX],adj[MAX<<1],nxt[MAX<<1]; 7 LL ans[MAX],val[MAX],son[MAX],in[MAX]; 8 void addedge(int u,int v){ 9 tot++; 10 adj[tot]=v; 11 nxt[tot]=head[u]; 12 head[u]=tot; 13 } 14 void dfs1(LL x,LL fa){ 15 //if (in[x]==0) son[x]=1; 16 LL i,j;bool flag=true; 17 for (i=head[x];i;i=nxt[i]){ 18 if (adj[i]==fa) continue; 19 dfs1(adj[i],x); 20 flag=false; 21 son[x]+=son[adj[i]]; 22 val[x]+=val[adj[i]]; 23 ans[x]=max(ans[x],ans[adj[i]]); 24 } 25 if (flag) son[x]=1; 26 ans[x]=max(ans[x],(val[x]-1)/son[x]+1); 27 } 28 29 int main(){ 30 freopen ("c.in","r",stdin); 31 freopen ("c.out","w",stdout); 32 LL i,j,x; 33 scanf("%lld",&n); 34 memset(head,0,sizeof(head)); 35 memset(in,0,sizeof(in)); 36 memset(ans,0,sizeof(ans)); 37 for (i=2;i<=n;i++){ 38 scanf("%lld",&x); 39 addedge(i,x); 40 addedge(x,i); 41 in[x]++; 42 } 43 for (i=1;i<=n;i++) scanf("%lld",val+i); 44 bool flag=true; 45 for (i=1;i<=n;i++) if (val[i]!=0) {flag=false;break;} 46 if (flag) {printf("0");return 0;} 47 dfs1(1,0); 48 printf("%lld",ans[1]); 49 return 0; 50 }