(树形dp)Binary Apple Tree

Let’s imagine how apple tree looks in binary computer world. You’re right, it looks just like a binary tree, i.e. any biparous branch splits up to exactly two new branches. We will enumerate by integers the root of binary apple tree, points of branching and the ends of twigs. This way we may distinguish different branches by their ending points. We will assume that root of tree always is numbered by 1 and all numbers used for enumerating are numbered in range from 1 to N, where N is the total number of all enumerated points. For instance in the picture below N is equal to 5. Here is an example of an enumerated tree with four branches:
2 5
\ /
3 4
\ /
1
As you may know it’s not convenient to pick an apples from a tree when there are too much of branches. That’s why some of them should be removed from a tree. But you are interested in removing branches in the way of minimal loss of apples. So your are given amounts of apples on a branches and amount of branches that should be preserved. Your task is to determine how many apples can remain on a tree after removing of excessive branches.

题意是形如二叉树的苹果树,有n个结点,要求我们选出q个树杈使苹果的总数尽可能多
选出q个树杈的dp方程有点难想,转换为选出q+1个结点,可以用dp[i][j]表示第i个结点保留j个结点的最大值,则dp[i][j] = max(dp[i的左儿子][k] + dp[i的右儿子][j-k-1]) + w;
题目可能给的不是正规的二叉树,先dfs生成二叉树

#include
using namespace std;
typedef long long ll;

const int maxn = 100 + 4;
int dp[maxn][maxn];
vector< pair > E[maxn];
struct node {
    int l, r, w;
    node() {}
    node(int _l, int _r, int _w) : l(_l), r(_r), w(_w){}
} od[maxn];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, q;
    while(cin >> n >> q) {
        for(int i = 1; i <= n; i++) E[i].clear();
        memset(dp, 0, sizeof(dp));
        int u, v, w;
        for(int i = 1; i < n; i++) {
            cin >> u >> v >> w;
            E[u].emplace_back(make_pair(v, w));
            E[v].emplace_back(make_pair(u, w));
        }
        function dfs = [&](int u, int pre) {
            if(E[u].size() == 1 && E[u][0].first == pre) {
                od[u].l = od[u].r = 0;
                return;
            }
            for(auto& x : E[u]) {
                int v = x.first, w = x.second;
                if(v == pre) continue;
                if(od[u].l) od[u].r = v;
                else od[u].l = v;
                od[v].w = w;
                dfs(v, u);
            }
        };
        dfs(1, 0);
        function tree_dp = [&](int u, int pre, int sz) {
            if(sz <= 0) return 0;
            if(dp[u][sz]) return dp[u][sz];
            if(od[u].l == 0 && od[u].r == 0) return od[u].w;
            int mx = 0;
            for(int i = 0; i < sz; i++) {
                int l = tree_dp(od[u].l, u, i);
                int r = tree_dp(od[u].r, u, sz - i - 1);
                mx = max(mx, l + r);
            }
            return dp[u][sz] = mx + od[u].w;
        };
        tree_dp(1, 0, q + 1);
        cout << dp[1][q + 1] << endl;
    }
}

你可能感兴趣的:(总结)