P2015 Binary Apple Tree (depending on tree dp)

Title description
There is an apple tree. If the branch has branches, it must be two branches (that is, there is no node with only 1 son).
The tree has N nodes (leaf points or branch branch points), numbered 1-N, the root number must be 1.
We use the number of nodes connected at both ends of a branch to describe the position of a branch. Below is a tree with 4 branches

2   5
 \ / 
  3   4
   \ /
    1

Now there are too many branches on this branch and need to be pruned. But some branches have apples.
Given the number of branches that need to be retained, find the maximum number of apples that can be retained.

Input format
Two numbers in line 1, N and Q (1<=Q<= N,1<N<=100).
N represents the number of nodes in the tree, and Q represents the number of branches to be kept. The next line N-1 describes the information of the branch.
There are 3 integers per line, and the first two are the numbers of the nodes it connects. The third number is the number of apples on this branch.
There are no more than 30,000 apples on each branch.

Output format
A number, the maximum number of apples that can be retained.

Input and output sample
input

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

Output

21

Algorithm (tree dp)

This question requires a tree to have Q edges, can it be divided into sub-trees with K edges, roots and sub-trees with Qj-1 (why reduce one, I will talk about it later), which fits the tree shape The dp parent-child node has a dependency relationship with the son node, so we choose tree dp.

Idea:
Let f [u] [k] f[u][k]f [ u ] [ k ] represents the maximum number of apples that select k edges of the subtree with u as the root node. According to the dependency relationship mentioned above, we can list the dynamic transition equation:
f [u] [j] = max (f [u] [j], f [u] [j − 1 − k], f [v] [k] + w) f[u][j]=max(f[u][j],f[u][j-1-k],f[v][k]+w)f[u][j]=max(f[u][j],f[u][j1k],f[v][k]+w )
*Explain: u represents the parent node, v is its own child node, j represents a total of j edges, k represents k edges selected on the subtree, and w represents the edge weight of u->v;Why a total of j-1 edges* Because we think you want to select edges on the subtree now, do we have to connect the current point to the subtree before we can select edges! So we are j-1 (because the current point and an edge of the subtree have been selected)

  • The data is not big, we can choose adjacency matrix or adjacency list, but the adjacency matrix is ​​simpler.
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#define ll long long
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
using namespace std;
const int MAX=2147483647;
const int N=1e2+10;
struct node
{
    
    
	int u,v,w,next;
} e[2*N];
int n,m,hd[N],tot,f[N][N],sz[N];
void add(int x,int y,int w) {
    
    e[++tot]=(node){
    
    x,y,w,hd[x]};hd[x]=tot;}
void dfs(int u,int fa)
{
    
    
	for(int i=hd[u];i;i=e[i].next)
	{
    
    
		int v=e[i].v;if(v==fa) continue;
		dfs(v,u);sz[u]+=sz[v]+1;  //子树边数在加上子节点子树的基础上还要加一,也就是连接子节点子树的那条边
		for(int j=min(m,sz[u]);j>=0;j--)   //由于是01背包,所以要倒序DP
			for(int k=min(j-1,sz[v]);k>=0;k--)  //这一维正序倒序无所谓,但是把取min放在初始化里可以减少运算次数,算是一个优化的小习惯
				f[u][j]=max(f[u][j],f[u][j-k-1]+f[v][k]+e[i].w);
	}
}
int main()
{
    
    
	scanf("%d%d",&n,&m);
	for(int i=1;i<n;i++)
	{
    
    
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);  //但我闲得慌,选用邻接表
		add(v,u,w);
	}
	dfs(1,-1);  //这里的fa不能为1,因为if(v==fa) continue;
	printf("%d",f[1][m]);  //题目已经给出了根节点是1,千万别把它看成无根树来做
	return 0;
}

Guess you like

Origin blog.csdn.net/bigwinner888/article/details/108017865