CF 1065F F. Up and Down the Tree( 树形dp)

版权声明:本文为博主原创文章,转载请在下面留个言就好 https://blog.csdn.net/Dylan_Frank/article/details/83098237

文章目录

题目连接

F. Up and Down the Tree

分析

官网题解

个人翻译:

可以分两步dp:

  1. dp[u] : 以 u u 为根的节点访问完所有能访问的叶子节点并回到 u u 所能获得的最大叶子数目,low[u], 这种情况下所能获得的最低的叶子深度(dep最小),这两个东西是完全独立的可以一起弄
  2. ans[u]: 以 u 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;
}

猜你喜欢

转载自blog.csdn.net/Dylan_Frank/article/details/83098237