版权声明:本文为博主原创文章,转载请在下面留个言就好 https://blog.csdn.net/Dylan_Frank/article/details/83098237
题目连接
分析
个人翻译:
可以分两步dp:
- dp[u] : 以 为根的节点访问完所有能访问的叶子节点并回到 所能获得的最大叶子数目,low[u], 这种情况下所能获得的最低的叶子深度(dep最小),这两个东西是完全独立的可以一起弄
- ans[u]: 以 为根的节点所能获得的最大叶子数目,不要求返回这棵树,这个可对于每颗子树讨论,考虑从子树返回和不从子树返回两种情况就好了
code
#include<bits/stdc++.h>
using namespace std;
#define MAX_VAL 1000005
#define MAX_ARRAY_SIZE 1000005
#define ms(x,v) memset((x),(v),sizeof(x))
#define pb push_back
#define fi first
#define se second
#define mp make_pair
#define INF 0x3f3f3f3f
typedef long long LL;
typedef pair<int,int> Pair;
int n,k;
std::vector<int> G[MAX_ARRAY_SIZE];
int dp[MAX_ARRAY_SIZE];
int dep[MAX_ARRAY_SIZE];
int low[MAX_ARRAY_SIZE];
int ans[MAX_ARRAY_SIZE];
void dfs1(int v,int p) {
dep[v] = dep[p] +1;
if(G[v].empty()){
low[v] = dep[v];
dp[v] = 1;
}else{
int h = INF;
int val =0;
for(int u : G[v]){
dfs1(u,v);
if(low[u] - dep[v] <=k){
val += dp[u];
h = min(h,low[u]);
}
}
dp[v] =val;
low[v] =h;
}
}
void dfs(int v) {
ans[v] = dp[v];
for(int u : G[v]){
dfs(u);
int tmp = dp[v];
if(low[u] - dep[v] <=k)tmp -= dp[u];
ans[v] = max(ans[v],tmp + ans[u]);
}
}
int main (int argc, char const *argv[]) {
ios_base::sync_with_stdio(0);
cin.tie(0);
/**************begin AC code******************/
cin >> n >> k;
for(int i=2 ; i<=n ; ++i){
int p;
cin >> p;
G[p].pb(i);
}
dep[0]=0;
dfs1(1,0);
dfs(1);
std::cout << ans[1] << '\n';
/**************end AC code******************/
return 0;
}