题解 | #牛牛种小树#

牛牛种小树

https://ac.nowcoder.com/acm/contest/11179/D

题目大意

给你n个点,f函数的值,现在你要构造一棵树,一个度数为k的点有f(k)点贡献,问你最大贡献


解题思路

对于一棵树,除了根节点每个点都有一个父亲节点,而一个点的度数就是父亲节点数量+子节点数量

那么可以先构造一颗所有点都连向1的数(1为根节点),且先不计算根节点的贡献,那么贡献就是(n-1)*f(1)

注:下文只对深度为2的点进行修改,深度大于2的点的儿子关系已经确定,无需修改,不然会出现重复计算

之后考虑把一些点移到其他点的儿子中,设为1的儿子有i个时的最大贡献,那么每次可以以x的代价制造f(x+1)-f(1)点贡献(x<i,将1的x个儿子移到某个点的儿子中,该点度数从1变为了x+1,贡献为f(x+1)-f(1))

这个过程和背包相似,所以从小到大枚举可以做到每种贡献可以选无限个(完全背包)

最后结果即为(加上根节点的贡献)


code

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define N 10100
using namespace std;
int n;
ll ans,f[N],a[N];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<n;++i)
        scanf("%lld",&a[i]);
    memset(f,-127/3,sizeof(f));
    f[n-1]=a[1]*(n-1);//初始(n-1)个点度数为1,根节点不算
    for(int i=1;i<n-1;++i)//儿子个数为i
        for(int j=n-1-i;j>0;--j)
            f[j]=max(f[j],f[j+i]+a[i+1]-a[1]);
    for(int i=1;i<=n-1;++i)
        ans=max(ans,f[i]+a[i]);//补上根节点的贡献
    printf("%lld",ans);
    return 0;
}
全部评论

相关推荐

昨天 11:15
中南大学 Java
好可爱的hr姐姐哈哈哈哈
黑皮白袜臭脚体育生:兄弟们貂蝉在一起,吕布开了
点赞 评论 收藏
分享
05-14 20:34
门头沟学院 Java
窝补药贝八股:管他们,乱说,反正又不去,直接说680
点赞 评论 收藏
分享
05-21 15:47
门头沟学院 Java
浪漫主义的虹夏:项目有亮点吗,第一个不是纯玩具项目吗,项目亮点里类似ThreadLocal,Redis储存说难听点是花几十分钟绝大部分人都能学会,第二个轮子项目也没体现出设计和技术,想实习先沉淀,好高骛远的自嗨只会害了自己
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务