推荐一道联赛练习题。
题目分析:
你考虑进入一个子树就可能上不来了,如果上得来的话就把能上来的全捡完然后走一个上不来的,所以这就是个基本的DP套路。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 1002000; 5 6 int n,k,fa[maxn]; 7 vector <int> g[maxn]; 8 9 int dep[maxn],minn[maxn]; 10 11 int f[maxn],d[maxn]; 12 13 void read(){ 14 scanf("%d%d",&n,&k); 15 for(int i=2;i<=n;i++) {scanf("%d",&fa[i]);g[fa[i]].push_back(i);} 16 } 17 18 void dfs(int now,int dp){ 19 dep[now] = dp; 20 if(g[now].size() == 0){minn[now] = dp; return;} 21 minn[now] = 1e8; 22 for(int i=0;i<g[now].size();i++){ 23 dfs(g[now][i],dp+1); 24 minn[now] = min(minn[now],minn[g[now][i]]); 25 } 26 } 27 28 void dfs2(int now){ 29 if(g[now].size() == 0){ 30 f[now] = d[now] = 1; 31 return; 32 } 33 for(int i=0;i<g[now].size();i++) dfs2(g[now][i]); 34 for(int i=0;i<g[now].size();i++) 35 if(minn[g[now][i]] - dep[now] <= k) d[now] += d[g[now][i]]; 36 for(int i=0;i<g[now].size();i++){ 37 if(minn[g[now][i]] - dep[now] <= k) 38 f[now] = max(f[now],d[now]-d[g[now][i]]+f[g[now][i]]); 39 else f[now] = max(f[now],d[now]+f[g[now][i]]); 40 } 41 } 42 43 void work(){ 44 dfs(1,1); 45 dfs2(1); // dp 46 printf("%d ",f[1]); 47 } 48 49 int main(){ 50 read(); 51 work(); 52 return 0; 53 }