苹果二叉树(题解)

题目描述


有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点)。这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1。 我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。下面是一颗有4个树枝的树:

2 5

\ /

3 4

\ /

1

现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。 给定需要保留的树枝数量,求出最多能留住多少苹果。

输入格式


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

输出格式


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

样例数据


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

output
21

Solution


f [ i ] [ j ] 表示到第i个节点保留j条枝条的最大苹果数量

因为是二叉树,所以我们枚举左孩子中保留的枝条数量,可以通过相减得到右孩子的枝条个数

状态转移方程:
f [ x ] [ j ] = m a x ( f [ x ] [ j ] , f [ x ] [ j k ] + f [ y ] [ k 1 ] + v a l u e )

对于x节点下的子节点j,对j保留多少枝条最优进行dp
在这里好好说明下,因为建树是我们是按照递归建的树。
进行比较时,f[x][j]都是前面选择除i外的子节点得到的最优解结果
所以dp的时候不可能重复或者漏掉某节点

代码:

 //By Bibi
///                 .-~~~~~~~~~-._       _.-~~~~~~~~~-.
///             __.'              ~.   .~              `.__
///           .'//                  \./                  \\`.
///        .'//                     |                     \\`.
///       .'// .-~"""""""~~~~-._     |     _,-~~~~"""""""~-. \\`.
///     .'//.-"                 `-.  |  .-'                 "-.\\`.
///   .'//______.============-..   \ | /   ..-============.______\\`.
/// .'______________________________\|/______________________________`.
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define dep(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
const int MAXN=110;
int inline read(){
    int sum=0,flag=1;
    char c;
    for(;c<'0'||c>'9';c=getchar())if(c=='-') flag=-1;
    for(;c>='0'&&c<='9';c=getchar())sum=(sum<<1)+(sum<<3)+c-'0';
    return sum*flag;
}
int n,q;
int v[MAXN];
struct edge{
    int y,next,v;
}e[MAXN<<1];
int f[MAXN][MAXN];
int link[MAXN];
int tot;
void inline insert(int x,int y,int v){
    e[++tot].y=y;e[tot].v=v;e[tot].next=link[x];link[x]=tot;
}
void inline init(){
    n=read(),q=read();
    int x,y,v;
    rep(i,1,n-1){
        x=read();y=read();v=read();
        insert(x,y,v);
        insert(y,x,v);
    }
}
int inline DP(int x,int fa){
    int ans=0;
    for(int i=link[x];i;i=e[i].next){
        int y=e[i].y;
        if(y==fa) continue;
        int v=e[i].v;
        ans+=DP(y,x)+1;
        dep(j,min(ans,q),1)
        dep(k,min(ans,j),1){
            f[x][j]=max(f[x][j],f[x][j-k]+f[y][k-1]+v);
        }
    }
    return ans;
}
int main(){
    init();
    DP(1,0);
    printf("%d",f[1][q]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/bbbblzy/article/details/80342923