• Serval and Rooted Tree(CF1153D)(树形dp)


    题意:
    题目给出一棵树,以结点 (1)为根,树上每个结点都有一个操作码 (flag)

    • (flag = 0),则这个结点的值为其孩子结点的最小值;
    • (flag = 1),则这个结点的值为其孩子结点的最大值;

    需要给每个叶子结点分配 (1sim k)的值(每个结点的值不重复)。问根结点的最大值为多少。


    想法:
    显然,对于直接通过某种方式去分配叶子结点的值是无法做到的。

    • 考虑树形dp的做法。我们可以考虑怎么求出根结点会受到几个叶子结点的影响,然后把最大的几个值分配给这几个结点即可。答案即是 (k-num+1)(k=叶子结点数) , (num=影响根结点的叶子数) )。

    • 设 $dp[i] $表示以结点 (i) 为根的子树中,结点 (i) 会受到几个叶子结点的影响。那么在转移方程中, 如果(flag[i]=1)(dp[i]=其子树中的dp最小值);如果 (flag[i]=0)(dp[i]=其子树的dp值之和)


    代码:

    int dp[maxn];
    vector<int>g[maxn];
    int n;
    int flag[maxn];
    
    void dfs(int x)
    {
        int maxx=0;
        int minx=inf;
        for(int i=0;i<g[x].size();i++){
            int v=g[x][i];
            dfs(v);
            minx=min(minx,dp[v]);
            maxx+=dp[v];
        }
        if(g[x].size()==0){
            dp[x]=1;
        }else{
            if(flag[x]==0){
                dp[x]=maxx;
            }else{
                dp[x]=minx;
            }
        }
    }
    int main()
    {
        cin>>n;
        for(int i=1;i<=n;i++){
            scanf("%d",&flag[i]);
        }    
        for(int i=2;i<=n;i++){
            int num;
            scanf("%d",&num);
            g[num].push_back(i);
        }
        dfs(1);
        int sum=0;
        for(int i=1;i<=n;i++){
            if(g[i].size()==0)sum++;
        }
        printf("%d",sum-dp[1]+1);
    }
    
    越自律,越自由
  • 相关阅读:
    Hashtable源码分析
    ConcurrentHashMap1.7源码分析
    JDK1.8新特性
    回炉Spring--Bean生命周期及AOP
    @DateTimeFormat 和 @JsonFormat 注解
    面向切面编程-日志切面应用及MDC使用
    maven 多模块开发
    maven 安装
    ztree树节点重叠问题
    Java问题解读系列之IO相关---Java深拷贝和浅拷贝
  • 原文地址:https://www.cnblogs.com/ha-chuochuo/p/14322638.html
Copyright © 2020-2023  润新知