链接:https://ac.nowcoder.com/acm/contest/11179/D
来源:牛客网
题目描述
牛牛最近在学数据结构。他打算用他得到的米粒去构造一棵有n个节点的树,并使得它的价值最大。
设f(d)表示树上度数为d的一个点能够获取的最大价值。则这棵树的价值为
∑
i
=
1
n
f
(
d
i
)
,
其
中
d
i
表
示
第
i
个
点
的
度
数
。
\sum_{i=1}^nf(d_i),其中d_i 表示第i个点的度数。
i=1∑nf(di),其中di表示第i个点的度数。
刚刚比赛做到了这道题,卡了一个小时
后来仔细一想,的确很简单
先固定根部,这样接下来插在根部的叶子就不会影响根部,然后就是一个简单背包了
背包:
对于整张图来说,总共有2*n-2地度数,由于每一个点都至少有一个度数,我们就只剩下n-2的度数可以进行自由分配
我们将每个点看做一个点加上一条没有连上其他点的边,然后在更新的时候将所有点联向当前树的叶子节点上,然后根据其度数做一下背包就好了
f[i] 表示树上已经有i 个点的最佳权值
i循环背包物品种类,从1到n-1,j循环决策即背包容积
果然还是太菜了…
#include<bits/stdc++.h>
using namespace std;
#define N 10010
typedef long long LL;
int n,f[N];
LL dp[N];
int main(){
cin >> n;
for(int i=1;i<n;i++){
cin >> f[i];
if(i>1) f[i]-=f[1];
}
memset(dp,-0x3f,sizeof dp);
dp[0]=n*f[1];
for(int i=1;i<n;i++)
for(int j=i;j<=n-2;j++)
dp[j]=max(dp[j],dp[j-i]+f[i+1]);
cout << dp[n-2] << endl;
return 0;
}