zoukankan      html  css  js  c++  java
  • libreoj #10153 树形dp

    $des$

    有一棵二叉苹果树,如果数字有分叉,一定是分两叉,即没有只有一个儿子的节点。这棵树共 NNN 个节点,标号 1 至 N,树根编号一定为 1

    我们用一根树枝两端连接的节点编号描述一根树枝的位置。一棵有四根树枝的苹果树,因为树枝太多了,需要剪枝。但是一些树枝上长有苹果,给定需要保留的树枝数量,求最多能留住多少苹果

    $sol$

    树形dp

    $f_{i, j}$ 表示以 $i$ 为根的子树中保留 $j$ 个的最大值

    转移时枚举该子树保留了多少以及两个儿子分别保留了多少

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define Rep(i, a, b) for(int i = a; i <= b; i ++)
    
    const int N = 105;
    
    vector <pair <int, int> > G[N];
    int n, Q;
    int f[N][N];
    
    void Dfs(int u, int fa) {
        int S = G[u].size();
        int v1 = -1, w1, v2 = -1, w2;
        Rep(i, 0, S - 1) {
            pair<int, int> P = G[u][i];
            if(P.first == fa) continue;
            if(v1 == -1) v1 = P.first, w1 = P.second;
            else v2 = P.first, w2 = P.second;
            if(v1 == -1 || v2 == -1) continue;
            Dfs(v1, u);
            Dfs(v2, u);
            Rep(q, 1, Q) {
                Rep(l, 0, q) {
                    int r = q - l;
                    if(l == 0) f[u][q] = max(f[u][q], f[v2][r - 1] + w2);        
                    else if(r == 0) f[u][q] = max(f[u][q], f[v1][l - 1] + w1);    
                    else f[u][q] = max(f[u][q], f[v1][l - 1] + w1 + f[v2][r - 1] + w2);
                }
            }
        }
    }
    
    int main() {
        cin >> n >> Q;
        Rep(i, 1, n - 1) {
            int u, v, w; cin >> u >> v >> w;
            G[u].push_back(make_pair(v, w));
            G[v].push_back(make_pair(u, w));
        }
        Dfs(1, 0);
        cout << f[1][Q];
        return 0;
    }
  • 相关阅读:
    【NOIP2007】守望者的逃离
    20200321(ABC)题解 by 马鸿儒 孙晨曦
    20200320(ABC)题解 by 王一帆
    20200319(ABC)题解 by 王一帆 梁延杰 丁智辰
    20200314(ABC)题解 by 董国梁 蒋丽君 章思航
    20200309(ABC)题解 by 梁延杰
    20200307(DEF)题解 by 孙晨曦
    20200306(ABC)题解 by 孙晨曦
    20200305(DEF)题解 by 孙晨曦
    20200303(ABC)题解 by 王锐,董国梁
  • 原文地址:https://www.cnblogs.com/shandongs1/p/9874707.html
Copyright © 2011-2022 走看看