zoukankan      html  css  js  c++  java
  • luoguP5521 [yLOI2019] 梅深不见冬

    luoguP5521 [yLOI2019] 梅深不见冬

    Description

    给定一棵 n个节点的树,在树上行走,每次要么选择一个没有到达过的子节点,要么返回父节点。想要在一个节点 u 放上梅花当且仅当 u 的任意子节点 v 都被放上了 w​ 朵梅花。在任意时刻可以收回任意节点的梅花。对于每个节点,求如果想在这个节点放梅花,则至少需要准备多少梅花。

    Solution

    容易注意到叶子节点的答案一定是本身的权值

    而非叶节点一定是由下面的点限制的

    因此考虑自底向上处理

    显然对于一个节点i,他的答案最优是自身权值和所有儿子权值之和

    不能达到最优在于有可能儿子所需的答案更大

    于是考虑保证每个儿子都能填数,显然儿子所需的答案已经处理出来了

    显然当你填了一个数后他的前置节点就不需要再放数了,也就是说这一部分可以在儿子间重复利用

    很显然前置最多的那个点的前置的梅花一定可以反复放在其他儿子上

    所以说答案一定不会大于这个点本身的值加上儿子的值再加上最多的前置

    但是这一部分前置有一部分可以回收放在节点的权值上

    所以考虑按前置排序,每次保证当前前置的时候尽可能多的放在节点上

    答案显然更优

    #include<bits/stdc++.h>
    
    using namespace std;
    
    inline int read()
    {
        int f = 1,x = 0;
        char ch;
        do
        {
            ch = getchar();
            if(ch == '-') f = -1;
        }while(ch < '0'|| ch > '9');
        do
        {
            x = (x<<3) + (x<<1) + ch - '0';
            ch = getchar();
        }while(ch >= '0'&&ch <= '9');
        return f*x;
    }
    
    const int MAXN = 100000 + 10;
    
    int n;
    int ans[MAXN],f[MAXN],g[MAXN];
    int w[MAXN];
    vector<int>G[MAXN];
    vector<pair<int,int> >son[MAXN];
    
    inline void dfs(int x)
    {
        ans[x] = w[x];
        if(!G[x].size()) return;
        for(int i=0;i<G[x].size();i++)
        {
            int v = G[x][i];
            dfs(v);
            son[x].push_back(make_pair(ans[v] - w[v],v));
        }
        sort(son[x].begin(),son[x].end());
        int res = 0;
        int sum = 0;
        for(int i=son[x].size()-1;i>=0;i--)
        {
            int v = son[x][i].second;
            if(res < ans[v])
            {
                sum += (ans[v] - res);
                res = ans[v] - w[v];
            }
            else res -= w[v];
        }
        if(res < w[x]) sum += (w[x] - res);
        ans[x] = sum;
    //    cout << x << " " << f[x] << " " << ans[x] << " " << maxv << " " << w[maxi] << endl;
        return;
    }
    
    int main()
    {
        n = read();
        for(int i=2;i<=n;i++)
        {
            G[read()].push_back(i);
        }
        for(int i=1;i<=n;i++) w[i] = read();
        dfs(1);
        for(int i=1;i<=n;i++) printf("%d ",ans[i]);
    }
  • 相关阅读:
    Python之利用 gensim的word2vec进行酒店评论+wiki百科语料联合词向量训练
    Python之酒店评论主题提取LDA主题模型
    Python之酒店评论分词、词性标注、TF-IDF、词频统计、词云
    Pycharm使用技巧----Pycharm工程使用anaconda环境
    Python之Pandas 简介与Pandas 读取csv文件及相关操作01
    csv文件用excel打开乱码的解决方案
    apply()和call()的方法
    如何将webstrom本地的代码上传到github上
    通过Ajax方式上传文件,使用FormData进行Ajax请求
    Express bodyParser中间件使用方式
  • 原文地址:https://www.cnblogs.com/wlzs1432/p/13783002.html
Copyright © 2011-2022 走看看