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

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

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

输入格式

第一行两个数 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;
}

原文地址:https://www.cnblogs.com/lsyyy/p/11432947.html

时间: 2024-10-17 18:05:48

二叉苹果树(由根分为左子树和右子树两部分情况)的相关文章

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

二叉苹果树 题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号来描述一根树枝的位置.下面是一颗有4个树枝的树 2 5 \ / 3 4 \ / 1 现在这颗树枝条太多了,需要剪枝.但是一些树枝上长有苹果. 给定需要保留的树枝数量,求出最多能留住多少苹果. 输入输出格式 输入格式: 第1行2个数,N和Q(1<=Q<= N,1<N<=100)

二叉苹果树(树型DP+背包)

二叉苹果树 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点).这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号来描述一根树枝的位置.下面是一颗有4个树枝的树: 2   5 \  / 3  4 \  / 1 现在这颗树枝条太多了,需要剪枝.但是一些树枝上长有苹果. 给定需要保留的树枝数量,求出最多能留住多少苹果. 程序名:apple 输入格式: 第1行2个数,N和Q(1<=Q<= N,1<N<=

luogu P2015 二叉苹果树

P2015 二叉苹果树 题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号来描述一根树枝的位置.下面是一颗有4个树枝的树 2        5 \     / 3   4 \ / 1 现在这颗树枝条太多了,需要剪枝.但是一些树枝上长有苹果. 给定需要保留的树枝数量,求出最多能留住多少苹果. 输入输出格式 输入格式: 第1行2个数,N和Q(1<=Q<

luoguP2015 二叉苹果树

luoguP2015 二叉苹果树 题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号来描述一根树枝的位置.下面是一颗有4个树枝的树 2 5 \ / 3 4 \ / 1 现在这颗树枝条太多了,需要剪枝.但是一些树枝上长有苹果. 给定需要保留的树枝数量,求出最多能留住多少苹果. 输入输出格式 输入格式: 第1行2个数,N和Q(1<=Q<= N,1<

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

[Luogu2015] 二叉苹果树 题目描述 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号来描述一根树枝的位置.下面是一颗有4个树枝的树 2 5 \ / 3 4 \ / 1 现在这颗树枝条太多了,需要剪枝.但是一些树枝上长有苹果. 给定需要保留的树枝数量,求出最多能留住多少苹果. 输入输出格式 输入格式: 第1行2个数,N和Q(1<=Q<= N,1&l

MZOJ 1134 &amp;&amp; LuoGu P2015 二叉苹果树

MZOJ 1134 && LuoGu P2015 二叉苹果树     [传送门] #include<bits/stdc++.h> using namespace std; const int maxn=500; int N,Q; int head[maxn],k=0; int w[maxn][maxn],f[maxn][maxn]; struct edge{ int v,w,nxt; }e[maxn<<1]; void init(){ freopen("i

交互二叉树的所有左子树和右子树.

递归实现: 真正对递归的调用过程很熟悉的哥们才很顺,虽然这个题目代码看起来不难,但是我在纸上画出调用过程后,才弄明白是什么个过程. 1 //交换所有二叉树的左子树和右子树. 2 void 3 swap(PNode p) { 4 if(!p) return; 5 6 swap(p->lchild); 7 swap(p->rchild); 8 9 PNode t; 10 t = p->lchild; 11 p->lchild = p->rchild; 12 p->rchil

二叉苹果树

题意/Description:     有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点) 这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号来描述一根树枝的位置.下面是一颗有4个树枝的树 2 5 \ / 3 4 \ / 1 现在这颗树枝条太多了,需要剪枝.但是一些树枝上长有苹果.给定需要保留的树枝数量,求出最多能留住多少苹果. 读入/Input:     第1行2个数,N和Q. N表示在树枚举的点数.Q表示应

7-4 是否同一棵二叉搜索树(25 分)

给定一个插入序列就可以唯一确定一棵二叉搜索树.然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到.例如分别按照序列{2, 1, 3}和{2, 3, 1}插入初始为空的二叉搜索树,都得到一样的结果.于是对于输入的各种插入序列,你需要判断它们是否能生成一样的二叉搜索树. 输入格式: 输入包含若干组测试数据.每组数据的第1行给出两个正整数N (≤)和L,分别是每个序列插入元素的个数和需要检查的序列个数.第2行给出N个以空格分隔的正整数,作为初始插入序列.最后L行,每行给出N个插入的元素,属于L个