zoukankan      html  css  js  c++  java
  • Codeforces Round #646 (Div. 2) E. Tree Shuffling(树上dp)

    题目链接:https://codeforces.com/contest/1363/problem/E

    题意

    有一棵 $n$ 个结点,根为结点 $1$ 的树,每个结点有一个选取代价 $a_i$,当前 $b_i$,目标数字 $c_i$ 。每次可以选择以一个结点为根节点的子树中的 $k$ 个结点交换它们的 $b_i$,总代价为 $k imes a_{root}$ ,判断能否把所有结点都变为目标数字以及最小代价。

    题解

    因为每棵子树都可以被包含进更大的子树中,所以对于每棵子树的根节点,它的最小选取代价可以取它自身和所有可能的父节点的最小值。

    计算每棵子树中需要交换的 $0$ 和 $1$ 的个数,用根节点的最小选取代价交换后,多余的 $0$ 或 $1$ 累加至父节点所在的子树即可。

    代码

    #include <bits/stdc++.h>
    using ll = long long;
    using namespace std;
    const int N = 2e5 + 10;
    
    vector<int> G[N];
    int a[N], b[N], c[N];
    int cnt[N][2];
    ll ans;
    
    void dfs(int u, int pre) {
        if (pre != 0) a[u] = min(a[u], a[pre]);
        for (auto v : G[u]) {
            if (v != pre) {
                dfs(v, u);
                cnt[u][0] += cnt[v][0];
                cnt[u][1] += cnt[v][1];
            }
        }
        if (b[u] != c[u]) cnt[u][b[u]]++;
        int mi = min(cnt[u][0], cnt[u][1]);
        ans += 2LL * mi * a[u];
        cnt[u][0] -= mi;
        cnt[u][1] -= mi;
    }
    
    int main() {
        int n; cin >> n;
        for (int i = 1; i <= n; i++)
            cin >> a[i] >> b[i] >> c[i];
        for (int i = 0; i < n - 1; i++) {
            int u, v; cin >> u >> v;
            G[u].push_back(v);
            G[v].push_back(u);
        }
        dfs(1, 0);
        cout << ((cnt[1][0] or cnt[1][1]) ? -1 : ans) << "
    ";
    }

    参考博客:https://www.cnblogs.com/axiomofchoice/p/13022886.html

  • 相关阅读:
    左耳听风
    极客时间-算法
    极客时间-左耳听风阅读笔记
    涨知识
    学做饭
    开发流程
    线上问题复盘
    反思学习复习练习
    系统安全(转)
    单元测试
  • 原文地址:https://www.cnblogs.com/Kanoon/p/13024219.html
Copyright © 2011-2022 走看看