洛谷P2015 二叉苹果树

洛谷P2015 二叉苹果树

题意:

给一棵二叉树,每条边有一个权值,去掉某些边之后,使剩下的二叉树边的权值之和最大

分析:

这是一个典型的树状DP题
状态转移方程: d p [ k ] [ u ] = m a x ( d p [ k ] [ u ] , d p [ k ] [ u v ] + d p [ s o n ] [ v 1 ] + v a l [ k ] [ i ] ) dp[k][u] = max(dp[k][u], dp[k][u - v] + dp[son][v - 1] + val[k][i]) dp[k][u]=max(dp[k][u],dp[k][uv]+dp[son][v1]+val[k][i])
d p [ k ] [ u ] dp[k][u] dp[k][u] 表示以编号为k的节点作为根节点的子树上留下来u条边时保留的最大苹果数
详解见注释中

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
int dp[maxn][maxn];
int n, q;
bool vis[maxn] = {0};              //标记已经访问过的点
vector<int> edge[maxn], val[maxn]; //edge数组存边的情况,val数组存边的权值
int dfs(int k)
{
    vis[k] = 1;
    int cnt = 0; //cnt记录当前以k为根节点的子树所包含的节点数目
    for (int i = 0; i < edge[k].size(); ++i)
    {
        int son = edge[k][i];
        if (vis[son]) //已访问过的节点不再访问
            continue;
        cnt += dfs(son) + 1;

        for (int u = min(cnt, q); u > 0; --u)
        {
            for (int v = min(u, q); v > 0; --v)
                dp[k][u] = max(dp[k][u], dp[k][u - v] + dp[son][v - 1] + val[k][i]); //dp[k][u - v]表示以k为根节点的树上除去以son为根节点的子树后保留u-v条边所能保留的最大苹果数
                                                                                     //dp[son][v-1]表示以son为根节点的子树上保留v-1条边所能保留的最大苹果数
                                                                                     //u-(u-v)-(v-1)=1即k节点和son节点之间的边
                                                                                     //因为存入时edge和val相对应,所以val[k][i]即是节点k和son之间边的权值
        }
    }
    return cnt;
}
int main(int argc, char const *argv[])
{
    scanf("%d%d", &n, &q);
    int u, v, x;
    for (int i = 1; i < n; ++i)
    {
        scanf("%d%d%d", &u, &v, &x);
        edge[u].push_back(v);
        edge[v].push_back(u);
        val[u].push_back(x);
        val[v].push_back(x);
    }
    dfs(1);
    printf("%d\n", dp[1][q]);
    return 0;
}
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务