zoukankan      html  css  js  c++  java
  • Codeforces Round #551 (Div. 2) D. Serval and Rooted Tree (树形dp)

    题目:http://codeforces.com/contest/1153/problem/D

    题意:给你一棵树,每个节点有一个操作,0代表取子节点中最小的那个值,1代表取子节点中最大的值,叶子节点的话就是自己置一个值,有k个子节点,那么每个子节点的值范围

    就是1-k,1-k只能用一次

    思路:贪心不好取,我肯定是要排列完才知道当前的值是哪个,但是我可以知道当前节点应该是取子节点中排名第几的那个,从而推出根节点1的排名,然后再输出就行,因为是要从

    子节点那里递归上来,所以我们采取树形dp

    #include<bits/stdc++.h>
    #define mod 1000000007
    #define maxn 300005
    using namespace std;
    vector<int> mp[maxn];
    int d[maxn];
    int dp[maxn];
    int n,z,num;
    void dfs(int x){
        int mn=0,mx=-1;
        for(int i=0;i<mp[x].size();i++){
            dfs(mp[x][i]);
            if(mx==-1) mx=dp[mp[x][i]];   //取最大值也就是取排名最小的那一位
            else mx=min(mx,dp[mp[x][i]]);
            mn+=dp[mp[x][i]];  //最小值也就是取最小的那个值,要先计算出包含多少个叶子节点,然后计算
        }
        if(mp[x].size()==0)//如果是叶子节点
        {
          dp[x]=1;//叶子结点排名第一
          num++;
        }
        else{
            if(d[x]==0) dp[x]=mn;   
            else dp[x]=mx;
        }
    }
    int main(){
        cin>>n;
        for(int i=1;i<=n;i++) cin>>d[i];
        for(int i=2;i<=n;i++){//建图
            cin>>z;
            mp[z].push_back(i);
        }
        dfs(1);
        cout<<num-dp[1]+1;
    }
  • 相关阅读:
    短URL
    Linux安装MySQL
    Ubuntu中安装MySQL
    安装交叉工具链arm-linux-gcc
    Linux安装—IP设置
    Linux内核概述
    Bash变量
    Shell登陆
    Linux—查看远程Linux系统运行时间
    Linux—查看路由
  • 原文地址:https://www.cnblogs.com/Lis-/p/10704192.html
Copyright © 2011-2022 走看看