P2015 二叉苹果树

这道树形dp我又跪了。。


这道题给你二叉树,共有\(n-1\)条边,每条边有边权,只有在父亲结点被保留的情况下才能算进答案,求保留\(m\)条边的答案最大值。

我拿起来就开始写,后来才发现是边权啊!

翻题解发现,还是那个老思路:边权变为点权。只要把每一条边的边权弄到终点的点权即可。

由于是树,所以不会有一个点有多个边连入,所以放心地写。

状态方程还是那个dp[u][j] = std::max(dp[u][j], dp[u][j - k] + dp[v][k])

我们添加点权的时候在那个dp[u][1]里面加上去就好了。

其他都跟前面的是一样的。

我没用到这个二叉树的性质

代码:

#include
#include
const int maxn = 1005;
struct Edges
{
    int next, to;
} e[maxn];
int head[maxn], tot;
int dp[maxn][maxn];
int n, m;
int weight[maxn];
void link(int u, int v)
{
    e[++tot] = (Edges){head[u], v};
    head[u] = tot;
}
int dfs(int u)
{
    int ans = 1;
    for(int i = head[u]; i; i = e[i].next)
    {
        int v = e[i].to;
        int t = dfs(v);
        ans += t;
        for(int j = ans; j; j--)
        {
            for(int k = 1; k <= m; k++)
            {
                if(j - k > 0) dp[u][j] = std::max(dp[u][j], dp[u][j - k] + dp[v][k]);
            }
        }
    }
    return ans;
}
int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i < n; i++)
    {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        link(u, v);
        dp[v][1] += w;
    }
    
    dfs(1);
    printf("%d\n", dp[1][m + 1]);
    return 0;
}

转载于:https://www.cnblogs.com/Garen-Wang/p/9450479.html

你可能感兴趣的:(P2015 二叉苹果树)