BZOJ4027/LG4107 「HEOI2015」兔子与樱花 树形DP+贪心

问题描述

LG4107


题解

首先,我们可以直接令结点 \(x\) 的权值为 \(c[x]+son_x\) ,发现将 \(x,y\) 合并,相当于增加 \(c[x]+c[y]-1\) 的重量。

容易想到对于每个结点 \(x\) ,贪心的从小到大合并 \(c[y],y \in son(x)\) ,可以获得最大的答案。


\(\mathrm{Code}\)

#include<bits/stdc++.h>
using namespace std;

template <typename Tp>
void read(Tp &x){
    x=0;char ch=1;int fh;
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-'){fh=-1;ch=getchar(); }
    else fh=1;
    while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    x*=fh;
}

const int maxn=2000007;

int n,m,ans;
int c[maxn];

vector<int>son[maxn];

bool comp(int x,int y){
    return c[x]<c[y];
}

void dp(int x){
    if(son[x].size()==0) return;
    for(auto y:son[x]) dp(y);
    sort(son[x].begin(),son[x].end(),comp);
    c[x]+=son[x].size();
    for(auto y:son[x]){
        if(c[x]+c[y]-1<=m){
            c[x]+=c[y]-1;
            ++ans;
        }
        else break;
    }
}

int main(){
    read(n);read(m);
    for(int i=1;i<=n;i++) read(c[i]);
    for(int i=1,k;i<=n;i++){
        read(k);
        for(int j=1,x;j<=k;j++){
            read(x);++x;
            son[i].push_back(x);
        }
    }
    dp(1);
    printf("%d\n",ans);
    return 0;
}
全部评论

相关推荐

点赞 评论 收藏
分享
03-24 17:57
门头沟学院 Java
yakuso:你这头像哈哈哈
点赞 评论 收藏
分享
03-26 13:04
已编辑
电子科技大学 算法工程师
xiaowl:你这个简历“条目上”都比较有深度性,但是实际上面试官又没法很好的评估你是怎么达到很多看上去很厉害的结果的。要避免一些看上去很厉害的包装,比如高效的内存复用策略的表达,如果仅是简单的一些内存共享机制,而且面试上也没有深挖的空间,就不要这样表达。比如,工程化模式本质上可能就是定义了一些abstract class,那也就没特别多值得讲的内容。建议简历上应该侧重那些你花了大量时间和精力解决、研究的问题,不要过分追求“丰富”,而是关注在技术深入度、问题解决能力的表现上。
没有实习经历,还有机会进...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务