• 2020牛客多校第九场B- Groundhog and Apple Tree


    https://ac.nowcoder.com/acm/contest/5674/B

    题意

    现在有一棵树,你要从1开始跳一遍所有的点并且每条边只能走两次,再回到1,每条边都有一个边权,你走过这条边会先消耗(w_i)点HP,每个点都有一个果子,吃掉这个果子会上升(a_i)点HP,你在任何时候的HP不能小于0.并且你如果休息一秒钟会恢复1点HP。问你最少要休息多少时间才能走完这棵树。

    题解

    (f[u])为遍历完子树增加多少体力,(g[u])表示体力为0遍历完子树最低减少到多少

    那么最后答案显然为(min(0, -g[1]))

    img

    考虑这张图,绿线左边的是增加体力为正的情况,显然要g大的的排在前面,这样保证最低点最高,对于绿线右边,可以想到,我们需要的是最低点低的,且增加体力相对多的排在前面,所以按f-g排序,按树形dp转移即可

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    struct READ {
        inline char read() {
        #ifdef _WIN32
            return getchar();
        #endif
            static const int IN_LEN = 1 << 18 | 1;
            static char buf[IN_LEN], *s, *t;
            return (s == t) && (t = (s = buf) + fread(buf, 1, IN_LEN, stdin)), s == t ? -1 : *s++;
        }
        template <typename _Tp> inline READ & operator >> (_Tp&x) {
            static char c11, boo;
            for(c11 = read(),boo = 0; !isdigit(c11); c11 = read()) {
                if(c11 == -1) return *this;
                boo |= c11 == '-';
            }
            for(x = 0; isdigit(c11); c11 = read()) x = x * 10 + (c11 ^ '0');
            boo && (x = -x);
            return *this;
        }
    } in;
    
    const int N = 1e5 + 50;
    int a[N];
    struct node {
        int v, w;
        node(int v = 0, int w = 0): v(v), w(w) {}
    };
    vector<node> G[N];
    ll f[N], g[N];//f遍历完子树增加多少体力,g体力为0遍历完子树最低减少到多少
    struct S1 {
        ll x, y;
        bool operator < (const S1 &b) const {
            return y > b.y;
        } 
    };
    struct S2 {
        ll x, y;
        bool operator < (const S2 &b) const {
            return x - y > b.x - b.y;
        }
    };
    
    void dfs(int u, int fa) {
        for (node e : G[u]) {
            if (e.v == fa) continue;
            dfs(e.v, u);
        }
        vector<S1> s1; vector<S2> s2;
        for (node e : G[u]) {
            if (e.v == fa) continue;
            f[e.v] -= 2ll * e.w;
            g[e.v] -= e.w;
            g[e.v] = min(g[e.v], (ll)-e.w);
            g[e.v] = min(g[e.v], f[e.v]);
            if (f[e.v] >= 0) s1.push_back({f[e.v], g[e.v]});
            else s2.push_back({f[e.v], g[e.v]});
        }
        sort(s1.begin(), s1.end()); sort(s2.begin(), s2.end());
        for (auto e : s1) {
            g[u] = min(g[u], e.y + f[u]);
            f[u] += e.x;
        }
        for (auto e : s2) {
            g[u] = min(g[u], e.y + f[u]);
            f[u] += e.x;
        }
        f[u] += a[u]; g[u] += a[u];
    }
    void solve() {
        int n; in >> n;
        for (int i = 1; i <= n; i++) in >> a[i], G[i].clear(), f[i] = g[i] = 0;
        for (int i = 1; i < n; i++) {
            int u, v, w; in >> u >> v >> w;
            G[u].push_back(node(v, w));
            G[v].push_back(node(u, w));
        }
        dfs(1, 0);
        printf("%lld
    ", max(0ll, -g[1]));
    }
    int main() {
        int t; in >> t;
        while (t--) solve();
        return 0;
    }
    
  • 相关阅读:
    金额与数字转化常用实用几个JS方法
    Jdb命令 The Java Debugger
    GLOBAL TEMPORARY TABLE
    安装与配置Nginx
    MySQL二进制安装与密码破解
    基于FPM构建企业RPM包
    安装Tomcat
    nginx配置优化
    DHCP原理及配置(三个小实验)
    DNS主、从服务器的配置
  • 原文地址:https://www.cnblogs.com/artoriax/p/13648818.html
Copyright © 2020-2023  润新知