二叉苹果树
题目描述
有一棵苹果树,如果树枝有分叉,一定是分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
要使得一棵树割掉k个节点后整棵树权值和最大。这个题目挺恶心人的处理起来也麻烦。因为虽然这题目保证是二叉树,但是他输入时并没有给我们两个点的先后顺序。也就是他输入u,v,w,你不知道u是v的父亲还是v是u的父亲。网上有很多人写这个题解时为了方便就乱搞,判断什么如果那个点左儿子为空就成为左儿子否则成为右儿子的什么鬼,一般都是水得过cv水不过luogu或者反过来的偏解。正确的姿势应该是用边表存储。像我的做法就是拿边表存储之后弄一个Find_father函数找出每一个节点的父亲。关于这个函数待会我会单独拉出来讲怎么实现。我还多做了一个其实可以不用这么做的无用功:我又跑了一遍枚举找出每个节点的左右儿子。前面麻烦的事干完,接下来我们就可以考虑dp了。由于题目给的权值都是边权,我们就可以进行一个骚操作:把每条边的权值都下移到那条边通向的儿子节点上,然后给根节点的权值置0。因为我们给了根节点1一个0的权值,所以我们要保留的节点数就从q变成q+1了!然后我们可以继续进行骚操作,用dp(i,j)表示保留j个节点,于是我们一开始就dp根节点:dp(1,q+1)。那么这个dp的函数该怎么写呢?我们设某一个子树要保留j个节点,而根节点是一定要保存的,因为如果你一开始就把根节点剪掉了就啥都没了嘛。所以根节点的以两个儿子为根的子树就总共要保存j-1个节点。有了思路,我们就可以设左子树保存k个节点,然后我们来枚举这个k,于是右子树就可以推出来是保存j-k-1个节点啦。然后我们就来找状态转移方程和最大值。修建中…
时间: 2024-12-05 11:06:48