zoukankan      html  css  js  c++  java
  • Codeforces 1153D Serval and Rooted Tree (简单树形DP)

    <题目链接>

    题目大意:

    Serval拥有的有根树有n个节点,节点1是根。 Serval会将一些数字写入树的所有节点。但是,有一些限制。除叶子之外的每个节点都有一个写入操作的最大值或最小值,表示该节点中的数字应分别等于其子节点中所有数字的最大值或最小值。

    假设树中有k个叶子。 Serval希望将整数1,2,...,k放到k个叶子上(每个数字应该只使用一次)。他喜欢大的数字,因此他希望最大化根的数字。作为他最好的朋友,你能帮助他吗?

    解题分析:

    不难想到,本题就是转化成求在满足题目求的情况下,传递到根节点的最少叶子节点个数。因为叶子节点的值是由我们自己够构造,所以我们只需要将那些能够传递到根节点的叶子节点,从大到小赋值,就能够让根节点的值最大,且它的最大值为ans-num+1(ans为叶子节点个数,num为传递到根节点的叶子节点个数)。

    #include <bits/stdc++.h>
    using namespace std;
    
    template<typename T>
    inline void read(T&x){
        x=0;int f=1;char c=getchar();
        while(c<'0' || c>'9'){ if(c=='-')f=-1;c=getchar(); }
        while(c>='0' && c<='9'){ x=x*10+c-'0';c=getchar(); }
        x*=f;
    }
    
    const int N = 3e5+5;
    int val[N],num[N],ans=0;
    vector<int>G[N];
    
    void dfs(int u){
        if(G[u].size()==0){ num[u]=1;ans++;return; }
        int tmp=0;
        for(int i=0;i<G[u].size();i++){
            int v=G[u][i];
            dfs(v);
            tmp+=num[v];     //得到所有子树的所有叶子节点个数
            if(val[u]==1)num[u]=min(num[u],num[v]);  //如果是max的话,要使传递到根节点的叶子个数最少,只需要选某颗子树中最少的叶子个数
            else num[u]=max(num[u],tmp);    //如果是min的话,别无选择,只能选子树中叶子节点最多的值
        }
    }
    
    int main(){
        int n;read(n);
        for(int i=1;i<=n;i++){
            read(val[i]);
            if(val[i]==1)num[i]=1e9;
            else num[i]=0;
        }
        for(int i=2;i<=n;i++){
            int u;read(u);
            G[u].push_back(i);
        }
        dfs(1);
        printf("%d
    ",ans-num[1]+1);     
    }
  • 相关阅读:
    C#深入浅出 修饰符(二)
    HDU 5785 Interesting
    HDU 5783 Divide the Sequence
    HDU 5781 ATM Mechine
    UVA 714 Copying Books
    uva 1471 Defense Lines
    UVA 11134 Fabled Rooks
    UVA 11572 Unique Snowflakes
    UVA 11093 Just Finish it up
    UVA 10954 Add All
  • 原文地址:https://www.cnblogs.com/00isok/p/10705602.html
Copyright © 2011-2022 走看看