Description
有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点)
这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1。
我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。下面是一颗有4个树枝的树
2 5
\ /
3 4
\ /
1
现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。
给定需要保留的树枝数量,求出最多能留住多少苹果。
Input
第1行2个数,N和Q(1 <= Q <= N,1 < N <= 100)。
N表示树的结点数,Q表示要保留的树枝数量。接下来N-1行描述树枝的信息。
每行3个整数,前两个是它连接的结点的编号。第3个数是这根树枝上苹果的数量。
每根树枝上的苹果不超过30000个。
Output
一个数,最多能留住的苹果的数量。
Sample Input
5 2
1 3 1
1 4 10
2 3 20
3 5 20
Sample Output
21
【参考程序】:
#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std;
struct node
{
int lc,rc;
int s;
} tree[220];
int F[110][110],apple[110][110];
bool vis[110];
int n,q;
void make_tree(int root)
{
vis[root]=true;
for (int i=1;i<=n;i++)
if (!vis[i] && apple[root][i]!=-1)
{
if (tree[root].lc==0) tree[root].lc=i;
else tree[root].rc=i;
tree[i].s=apple[root][i];
make_tree(i);
}
}
int tree_dp(int t,int k)
{
if (F[t][k]!=-1) return F[t][k];
if (t==0 || k==0)
{
F[t][k]=0; return 0;
}
F[t][k]=0;
for (int i=0;i<=k-1;i++)
{
int ls=tree_dp(tree[t].lc,i);
int rs=tree_dp(tree[t].rc,k-1-i);
if (F[t][k]<ls+rs) F[t][k]=ls+rs;
}
F[t][k]+=tree[t].s;
return F[t][k];
}
int main()
{
scanf("%d%d",&n,&q); q++;
memset(apple,-1,sizeof(apple));
int a,b,s;
for (int i=1;i<=n-1;i++)
{
scanf("%d%d%d",&a,&b,&s);
apple[a][b]=s; apple[b][a]=s;
}
memset(tree,0,sizeof(tree));
memset(vis,false,sizeof(vis));
make_tree(1);
memset(F,-1,sizeof(F));
int ans=tree_dp(1,q);
printf("%d\n",ans);
return 0;
}