题目:
题意:
给出一个二叉树,求在这棵树上按照 d f s dfs dfs序取 k k k个点权可以取得的最大值
分析:
爽快树形
d
p
dp
dp,不解释
但是需要注意,当根节点只有一个子节点时要特判,另一个要注意的是我们必须取到
k
k
k个
如果漏了上述两点,那么就会造成
100
→
50
100→50
100→50的惨案
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<list>
#include<ctime>
#include<iomanip>
#include<string>
#include<bitset>
#include<deque>
#include<set>
#define LL long long
using namespace std;
inline LL read(){
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
LL n=read(),k=read();
LL x[1005],son[1005][20],len[1005];
LL w[1005][1005];
void dt(LL u)
{
if(!len[u]) return;
LL v1=son[u][0],v2=son[u][1];
if(v1) dt(v1);
if(v2) dt(v2);
if(u==1) return;
for(LL i=0;i<=k;i++)
for(LL j=0;j<=k;j++)
{
if(i+j==0) continue;
if(i+j+1<=k&&v1&&v2) w[u][i+j+1]=max(w[u][i+j+1],w[v1][i]+w[v2][j]+x[u]);
if(i+1<=k&&v1) w[u][i+1]=max(w[v1][i]+x[u],w[u][i+1]);
if(j+1<=k&&v2) w[u][j+1]=max(w[u][j+1],w[v2][j]+x[u]);
}
return;
}
int main()
{
memset(w,0xcf,sizeof(w));
for(LL i=2;i<=n;i++) x[i]=read();
for(LL i=1;i<=n;i++)
{
LL a=read(),b=read();
son[i][0]=a;son[i][1]=b;
if(a+b) len[i]=1;
}
for(LL i=2;i<=n;i++) w[i][1]=x[i],w[i][0]=0;
dt(1);
LL s1=son[1][0],s2=son[1][1];
if(!s1) return !printf("%d",w[s2][k]);
if(!s2) return !printf("%d",w[s1][k]);
for(LL i=0;i<=k;i++)
{
int j=k-i;
w[1][k]=max(w[1][k],w[s1][i]+w[s2][j]);
}
cout<<w[1][k];
return 0;
}