zoukankan      html  css  js  c++  java
  • CodeForces1065F 树形dp

    http://codeforces.com/problemset/problem/1065/F

    你有一棵带有n个结点的树,根是结点1。有一个标记,最初在根结点处。你可以将标记移动到其他结点处。假设标记当前所在结点为v,你可以做出以下两种操作:
    
    将标记移动到v子树的任一叶子处。
    
    如果是结点v为叶子,则将标记向根移动不超过 k 次。换句话说,如果 h(v) 为结点 v 的深度 (根的深度为0),你可以将其移动到顶点 to ( to 为 v 祖先) 并且 h(v)−k≤h(to)。
    
    根不是叶子(即使它的度数是 1)。计算最多能访问多少叶子。
    
    输入格式:
    
    第一行包含两个整数 n 和 k (1<k<n≤10^6) --- 树中的顶点数和向上移动的限制。
    
    第二行包含 n-1个整数 第i个整数表示结点i+1的父亲 输入保证树合法,根为1。
    
    输出格式:
    
    输出一个整数,表示可以访问的最大叶子数。
    题意

    把问题想难了,想在树dp上同时用树状数组维护,然后一波操作把自己骚死了

    一个显然的贪心思想是从1开始将所有可以拿的结点全部拿完之后返回1,然后进入下一个结点,这样每次遍历到根节点的结果都是最优的,判断拿结点的方法用树dp操作一下,用dfs进行预处理即可。

    #include <map>
    #include <set>
    #include <ctime>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <string>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    using namespace std;
    inline int read(){int now=0;register char c=getchar();for(;!isdigit(c);c=getchar());
    for(;isdigit(c);now=now*10+c-'0',c=getchar());return now;}
    #define For(i, x, y) for(int i=x;i<=y;i++)  
    #define _For(i, x, y) for(int i=x;i>=y;i--)
    #define Mem(f, x) memset(f,x,sizeof(f))  
    #define Sca(x) scanf("%d", &x)
    #define Sca2(x,y) scanf("%d%d",&x,&y)
    #define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define Scl(x) scanf("%lld",&x);  
    #define Pri(x) printf("%d
    ", x)
    #define Prl(x) printf("%lld
    ",x);  
    #define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
    #define LL long long
    #define ULL unsigned long long  
    #define mp make_pair
    #define PII pair<int,int>
    #define PIL pair<int,long long>
    #define PLL pair<long long,long long>
    #define pb push_back
    #define fi first
    #define se second 
    typedef vector<int> VI;
    const double eps = 1e-9;
    const int maxn = 1e6 + 10;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7; 
    int N,M,K;
    struct Edge{
        int to,next;
    }edge[maxn * 2];
    int head[maxn],tot;
    void init(){
        memset(head,-1,sizeof(int) * (N + 3));
        tot = 0;
    }
    void addedge(int u,int v){
        edge[tot].next = head[u];
        edge[tot].to = v;
        head[u] = tot++;
    }
    int dp[maxn],dp2[maxn];
    void dfs(int t){
        if(head[t] == -1){
            dp[t] = 1; dp2[t] = K;
            return;
        }
        dp[t] = 0,dp2[t] = 0;
        for(int i = head[t]; ~i ; i = edge[i].next){
            int v = edge[i].to;
            dfs(v);
            if(dp2[v]) dp[t] += dp[v];
            dp2[t] = max(dp2[t],dp2[v] - 1); 
        }
    }
    int sum = 0;
    void DP(int t,int ans){
        if(head[t] == -1){
            ans++;
            sum = max(sum,ans);
        }
        for(int i = head[t]; ~i; i = edge[i].next){
            int v = edge[i].to;
            if(dp2[v]){
                DP(v,ans + dp[t] - dp[v]);
            }else{
                DP(v,ans + dp[t]);
            }
        }
    }
    int main()
    {
        Sca2(N,K); init();
        for(int i = 2; i <= N; i ++){
            int u; Sca(u);
            addedge(u,i);
        }
        int root = 1;
        dfs(1);
        DP(1,0);
        Pri(sum);
        #ifdef VSCode
        system("pause");
        #endif
        return 0;
    }
  • 相关阅读:
    pgspider sqlite mysql docker 镜像
    pgspider docker 镜像
    pgspider基于pg 的高性能数据可视化sql 集群引擎
    diesel rust orm 框架试用
    golang 条件编译
    Performance Profiling Zeebe
    bazel 学习一 简单java 项目运行
    一个好用node http keeplive agnet
    gox 简单灵活的golang 跨平台编译工具
    mailhog 作为smtp server mock工具
  • 原文地址:https://www.cnblogs.com/Hugh-Locke/p/9964244.html
Copyright © 2011-2022 走看看