二叉苹果树(由根分为左子树和右子树两部分情况)

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

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

tree.png

输入格式

第一行两个数 N和 Q,N 表示树的节点数, Q表示要保留的树枝数量。

接下来 N-1行描述树枝信息,每行三个整数,前两个是它连接的节点的编号,第三个数是这根树枝上苹果数量。

输出格式

输出仅一行,表示最多能留住的苹果的数量。


 

f[i][j]表示当前节点保留j根树枝的最大苹果数

 

#include<bits/stdc++.h> 
#define re return
#define inc(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x; 
}


const int maxn=105; 
int n,m,k,f[maxn][maxn],hd[maxn];
struct node{
    int to,nt,val;
}e[10005];

inline void add(int x,int y,int z)
{
    e[++k].to=y;e[k].nt=hd[x];hd[x]=k;e[k].val=z;
    e[++k].to=x;e[k].nt=hd[y];hd[y]=k;e[k].val=z;
}

inline void dfs(int x,int fa,int add)
{
    int son1=0,son2=0;//左右儿子
    for(int i=hd[x];i;i=e[i].nt)
    {
        int v=e[i].to;
        if(v==fa)continue;
        if(!son1)son1=v;
        else son2=v;
        dfs(v,x,e[i].val);    
    }
    
    if(x!=1)//非根节点累计自身苹果树 
    {    
        inc(i,1,m)
        inc(j,0,i-1)
        f[x][i]=max(f[x][i],f[son1][j]+f[son2][i-1-j]+add);
    }
    else //根节点累计儿子苹果数 
    {
        inc(j,0,m)
        f[x][m]=max(f[x][m],f[son1][j]+f[son2][m-j]);
    }
    
}


int main()
{
    freopen("in.txt","r",stdin);
    int x,y,z;
    rd(n),rd(m);
    inc(i,2,n)
    {
        rd(x);rd(y);rd(z);
        add(x,y,z);
    }
    
    dfs(1,0,0);
        
    printf("%d",f[1][m]);
    re 0;
}

 

 

posted @ 2019-08-30 08:10  凉如水  阅读(537)  评论(0编辑  收藏  举报