题目大意:
有一棵二叉苹果树,共有N个结点,编号为1~N,树根编号一定是1。用两个结点的编号来描述每一根树枝。现在这颗树枝条太多了,需要剪枝。但树枝上长有苹果。请问给定需要保留的树枝数量Q,求出最多能留住多少苹果。
输入格式:第1行2个数,N和Q(1<=Q<= N,1<N<=100)。N表示树的结点数,Q表示要保留的树枝数量。接下来N-1行描述树枝的信息。每行3个整数,前两个是它连接的结点的编号。第3个数是这根树枝上苹果的数量。每根树枝上的苹果不超过30000个。
输出格式:一个数,最多能留住的苹果的数量。
开始学习树形DP,先水了一道题。
这个DP很好想,f[i][j]表示以i为根选j个苹果的max
f[i][j]=max(f[i][j],f[i的左儿子][k]+f[i的右儿子][j-k-1]+f[i][1])
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=300;
struct node{
int x,y,z,next,other;
}sa[N];int len=0,first[N];
int n,k;
void ins(int x,int y,int z)
{
len++;
sa[len].x=x;
sa[len].y=y;
sa[len].z=z;
sa[len].next=first[x];
first[x]=len;
}
struct trnode
{
int l,r;
trnode()
{
l=r=0;
}
}tr[N];
bool tf[N];
int f[N][N];
void dfs(int x)
{
for(int i=first[x];i!=-1;i=sa[i].next)
{
int y=sa[i].y;
if(tf[y]==true)
{
tf[y]=false;
f[y][1]=sa[i].z;
if(tr[x].l==0) tr[x].l=y;
else tr[x].r=y;
dfs(y);
}
}
}
int tr_dp(int x,int m)
{
if(f[x][m]!=-1) return f[x][m];
int maxx=0;
for(int i=0;i<=m-1;i++)
{
int ls=i,rs=(m-1)-i;
int lans=tr_dp(tr[x].l,ls);
int rans=tr_dp(tr[x].r,rs);
maxx=max(maxx,lans+rans+f[x][1]);
}
f[x][m]=maxx;
return f[x][m];
}
int main()
{
scanf("%d%d",&n,&k);
memset(first,-1,sizeof(first));
for(int i=1;i<n;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
ins(x,y,z);
ins(y,x,z);
}
memset(tf,true,sizeof(tf));
memset(f,-1,sizeof(f));
tf[1]=false;
dfs(1);
for(int i=1;i<=n;i++) f[i][0]=0;
f[1][1]=0;
printf("%d\n",tr_dp(1,k+1));
}