zoukankan      html  css  js  c++  java
  • 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);
    }
    
    越自律,越自由
  • 相关阅读:
    CSS 之 div中文字超出时自动换行
    架构设计分享之权限系统(看图说话)
    perl杂项
    nginx比较apache
    Apache与Nginx的优缺点比较
    DVB系统中PCR的生成和PCR校正
    相关软件测试工具
    我遇到的有趣面试题:破解程序
    OpenStack 部署运维实战
    一些大公司的开源项目及代码托管平台
  • 原文地址:https://www.cnblogs.com/ha-chuochuo/p/14322638.html
Copyright © 2011-2022 走看看