[Luogu2015]二叉苹果树(树形dp)

Posted Frozen_Heart(AFO)

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Luogu2015]二叉苹果树(树形dp)相关的知识,希望对你有一定的参考价值。

[Luogu2015] 二叉苹果树

题目描述

有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点)

这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1。

我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。下面是一颗有4个树枝的树

2   5
  / 
  3   4
    /
    1

现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。

给定需要保留的树枝数量,求出最多能留住多少苹果。

输入输出格式

输入格式:

第1行2个数,N和Q(1<=Q<= N,1<N<=100)。

N表示树的结点数,Q表示要保留的树枝数量。接下来N-1行描述树枝的信息。

每行3个整数,前两个是它连接的结点的编号。第3个数是这根树枝上苹果的数量。

每根树枝上的苹果不超过30000个。

输出格式:

一个数,最多能留住的苹果的数量。

输入输出样例

输入样例#1:

5 2
1 3 1
1 4 10
2 3 20
3 5 20

输出样例#1:

21

一道树形dp的比较水的题目
(F[i][j])表示到第(i)个结点,其下保留了(j)个树枝所得的最多的苹果数。
套路地自下到上转移:
[F[i][j]=F[son1][x]+F[son2][y]+(v[son1])+(v[son2])]
(x+y=)(j-2)(j-1)(j),讨论一下即可。
具体看代码。

#include<cstring>
#include<algorithm>
#include<cstdio>
#include<iostream>
using namespace std;
int read()
{
    int x=0,w=1;char ch=getchar();
    while(ch>'9'||ch<'0') {if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*w;
}
int n,q,cnt;
int head[110];
int dp[110][110];
int son[110][2];
int w[110][2];
struct node{
    int v,to,next;
}edge[210];
void add(int x,int y,int z)
{
    cnt++;
    edge[cnt].to=y;
    edge[cnt].next=head[x];
    edge[cnt].v=z;
    head[x]=cnt;
}
void dfs(int,int);
int main()
{
    int x,y,z;
    n=read();q=read();
    for(int i=1;i<n;i++)
    {
        x=read();y=read();z=read();
        add(x,y,z);
        add(y,x,z);
    }
    dfs(1,0);
    cout<<dp[1][q];
}
void dfs(int k,int f)
{
    int num=0;
    int v;
    for(int i=head[k];i;i=edge[i].next)
    {
        v=edge[i].to;
        if(v==f) continue;
        son[k][num]=v;
        w[k][num]=edge[i].v;
        num++;
        dfs(v,k);
    }
    if(!num) return;
    for(int i=1;i<=q;i++)
    {
        for(int j=0;j<=i;j++)
        {
            if(j==0)
                dp[k][i]=max(dp[k][i],dp[son[k][1]][i-1]+w[k][1]);
            else if(j==i)
                dp[k][i]=max(dp[k][i],dp[son[k][0]][i-1]+w[k][0]);
            else 
                dp[k][i]=max(dp[k][i],dp[son[k][0]][j-1]+dp[son[k][1]][i-j-1]+w[k][0]+w[k][1]);
        }
    }
}

以上是关于[Luogu2015]二叉苹果树(树形dp)的主要内容,如果未能解决你的问题,请参考以下文章

树形背包(边)调试毒瘤LuoGu P2015 二叉苹果树

luogu P2015 二叉苹果树

Luogu-P2015 二叉苹果树

LuoguP2015 二叉苹果树 树形dp

P2015二叉苹果树 (树形DP分组背包)

二叉苹果树|codevs5565|luoguP2015|树形DP|Elena