题面
题目描述
有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点)。这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1。 我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。下面是一颗有4个树枝的树:
2 5
\ /
3 4
\ /
1
现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。 给定需要保留的树枝数量,求出最多能留住多少苹果。
输入格式
第1行2个数,N和Q(1<=Q<= N,1
题解
代表第i个点,保留j个枝条的最大数量。
这里的状态转移要注意,保留的j个枝条要分配到二叉树的两个子树中。
其他就没什么好说了。
还是裸题。
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int num=0;
char c=' ';
bool flag=true;
for(;c>'9'||c<'0';c=getchar())
if(c=='-')
flag=false;
for(;c>='0'&&c<='9';num=num*10+c-48,c=getchar());
return flag ? num : -num;
}
namespace graph{
const int maxn=120;
struct node{
int y,val;
};
vector<node>G[maxn];
int n,q;
void insert(int x,int y,int v){
G[x].push_back((node){y,v});
}
void init(){
n=read();q=read();
for(int i=1;i<n;i++){
int x=read();
int y=read();
int v=read();
insert(x,y,v);
insert(y,x,v);
}
}
}using namespace graph;
namespace DP_{
int f[maxn][maxn];
int dp(int u,int fa){
int size=G[u].size();
int ans=0;
for(int i=0;i<size;i++){
int v=G[u][i].y;
if(v==fa)continue;
ans+=dp(v,u)+1;
for(int j=min(ans,q);j>=1;j--){
for(int k=min(ans,j);k>=1;k--){
f[u][j]=max(f[u][j],f[u][j-k]+f[v][k-1]+G[u][i].val);
}
}
}
return ans;
}
}using namespace DP_;
int main(){
init();
dp(1,0);
printf("%d\n",f[1][q]);
return 0;
}