【题目描述】
有一棵苹果树,如果树枝有分叉,一定是分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个。
输出格式:
一个数,表示最多能留住的苹果的数量。
【输入输出样例】
输入样例:
5 2
1 3 1
1 4 10
2 3 20
3 5 20
输出样例:
21
【程序代码】
#include <bits/stdc++.h>
using namespace std;
const int maxn=200;
vector<int> G[maxn];
int ew[maxn][maxn]; //edge weight
/* f[i][j] represents the maximum number of apples that are retained
when j edges are retained in the subtree with node i as root */
int f[maxn][maxn];
int n,q;
int dfs(int x,int fa) {
int sum=0;
for(int i=0; i<G[x].size(); ++i) {
int s=G[x][i];
if(s==fa) continue;
sum+=dfs(s,x);
sum=sum+1;
for(int j=q; j>=1; --j) {
for(int k=1; k<=j; ++k) {
f[x][j]=max(f[x][j],f[x][j-k]+f[s][k-1]+ew[x][s]);
}
}
}
return sum;
}
int main() {
cin>>n>>q;
for(int i=1; i<n; ++i) {
int u,v,w;
cin>>u>>v>>w;
G[u].push_back(v);
G[v].push_back(u);
ew[u][v]=ew[v][u]=w; //edge weight
}
dfs(1,0);
cout<<f[1][q];
return 0;
}
/*
in:
5 2
1 3 1
1 4 10
2 3 20
3 5 20
out:
21
*/
【参考文献】
https://blog.csdn.net/qq_44013342/article/details/88555708
https://blog.csdn.net/qq_30974369/article/details/75246248
https://www.cnblogs.com/agenthtb/p/5858703.html
https://www.cnblogs.com/hanruyun/p/9788170.html