【P1303】苹果二叉树

时间:2022-10-15 16:33:14

树归入门题

原题:

有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点)。这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1。
我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。下面是一颗有4个树枝的树: 
2 5 
\ / 
3   4 
 \ / 
  1 
现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。
给定需要保留的树枝数量,求出最多能留住多少苹果。

1<=Q<= N,1<N<=100

每根树枝上的苹果不超过30000个。

核心思想是用f[x][y]表示以x为根的子树保留y条根的最大值

每次枚举i,f[x][y]=max(f[x][y],f[lchild][i]+f[rchild][y-i-1]),如果f[lchild][i]==0或f[rchild][y-i-1]==0,进去递归,求出f[lchild][i]或f[rchild][y-i-1]再更新

当size==1或y==0时要特判

刚开始写的时候写成先分别把lchild和rchild从0-size[lchild]或size[rchild]的最优值求出来,在枚举i更新x的从0-size[x]的最优值,不过这么做好想错了,看了oy学长的程序才改过来

不知道像上面这么写↑能不能写对,还需要做更多的题总结

代码:

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int read(){int z=,mark=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')mark=-; ch=getchar();}
while(ch>=''&&ch<=''){z=(z<<)+(z<<)+ch-''; ch=getchar();}
return z*mark;
}
struct ddd{int next,y,value;}e[];int LINK[],ltop=;
inline void insert(int x,int y,int z){e[++ltop].next=LINK[x];LINK[x]=ltop;e[ltop].y=y;e[ltop].value=z;}
struct dcd{int lchild,rchild,value,size;}tree[];
int n,m;
bool visited[];
int f[][];
void get_tree(int x,int y){
visited[x]=true;
tree[x].value=y;
for(int i=LINK[x];i;i=e[i].next)if(!visited[e[i].y]){
if(!tree[x].lchild) tree[x].lchild=e[i].y;
else tree[x].rchild=e[i].y;
get_tree(e[i].y,e[i].value);
}
tree[x].size=tree[tree[x].lchild].size+tree[tree[x].rchild].size+;
}
void tree_DP(int x,int y){
if(y==) f[x][y]=;
else if(!tree[x].lchild && !tree[x].rchild) f[x][y]=tree[x].value;
else{
for(int i=;i<y;i++){
if(f[tree[x].lchild][i]==) tree_DP(tree[x].lchild,i);
if(f[tree[x].rchild][y-i-]==) tree_DP(tree[x].rchild,y-i-);
f[x][y]=max(f[x][y],f[tree[x].lchild][i]+f[tree[x].rchild][y-i-]);
}
f[x][y]+=tree[x].value;
}
}
int main(){//freopen("ddd.in","r",stdin);
memset(visited,,sizeof(visited));
memset(tree,,sizeof(tree));
memset(f,,sizeof(f));
cin>>n>>m;
int _left,_right,_value;
for(int i=;i<n;i++){
_left=read(); _right=read(); _value=read();
insert(_left,_right,_value); insert(_right,_left,_value);
}
get_tree(,);
tree_DP(,m+);
cout<<f[][m+]<<endl;
return ;
}