zoukankan      html  css  js  c++  java
  • D. Chloe and pleasant prizes 树上dp + dfs

    http://codeforces.com/contest/743/problem/D

    如果我们知道mx[1]表示以1为根节点的子树中,点权值的最大和是多少(可能是整颗树,就是包括了自己)。那么,就可以O(n)扫一次各个点,对于每个点的儿子。

    选出最大的两个mx[son],更新答案即可。(注意这个节点只有1个或者没有儿子,就要是-inf)

    那么怎么得到这个mx[]呢?

    可以知道mx[father] = max(所有的mx[son])

    最后还要看看是否能选择整个树,所以用dp[cur]表示以cur为根的树的所有点券之和。

    然后就能dfs算出mx[]和dp[]。然后O(n)扫一次就好。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <assert.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    typedef long long int LL;
    const LL inf = 1e16L;
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    const int maxn = 2e5 + 20;
    int a[maxn];
    struct node {
        int u, v, w;
        int tonext;
    }e[maxn << 1];
    int first[maxn];
    int num;
    void add(int u, int v) {
        ++num;
        e[num].u = u;
        e[num].v = v;
        e[num].tonext = first[u];
        first[u] = num;
    }
    bool vis[maxn];
    LL dp[maxn];
    LL mx[maxn];
    void init(int cur) {
        dp[cur] = a[cur];
        mx[cur] = -inf;
        for (int i = first[cur]; i; i = e[i].tonext) {
            int v = e[i].v;
            if (vis[v]) continue;
            vis[v] = true;
            init(v);
            dp[cur] += dp[v];
            mx[cur] = max(mx[cur], mx[v]);
    //        mx[cur] = max(mx[cur], dp[v]);
        }
        mx[cur] = max(dp[cur], mx[cur]);
    }
    LL ans = -inf;
    void dfs(int cur, int fa) {
        LL mx1 = -inf, mx2 = -inf;
        int t = 0;
        for (int i = first[cur]; i; i = e[i].tonext) {
            int v = e[i].v;
            if (fa == v) continue;
            dfs(v, cur);
            t++;
            if (mx1 <= mx[v]) {
                mx2 = mx1;
                mx1 = mx[v];
            } else if (mx2 <= mx[v]) {
                mx2 = mx[v];
            }
        }
        if (t == 0 || t == 1) return;
        ans = max(ans, mx1 + mx2);
    }
    void work() {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; ++i) {
            scanf("%d", &a[i]);
        }
        for (int i = 1; i <= n - 1; ++i) {
            int u, v;
            scanf("%d%d", &u, &v);
            add(u, v);
            add(v, u);
        }
        vis[1] = true;
        init(1);
    //    printf("%d
    ", dp[6]);
    //    cout << mx[5] << endl;
        memset(vis, 0, sizeof vis);
        dfs(1, 0);
        if (ans <= -inf) {
            cout << "Impossible" << endl;
        } else cout << ans << endl;
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
    View Code
  • 相关阅读:
    Docker 私有仓库搭建
    事务提交与不同数据库的自增方式
    多环境切换&&注解方式&&增删改返回值问题
    查询缓存&&逆向工程
    Mybatis整合Log4j、延迟加载
    关联查询
    MyBatis实现动态SQL
    输出参数resultType
    MyBatis调用存储过程执行CRUD
    两种取值符号的异同
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6182940.html
Copyright © 2011-2022 走看看