BZOJ 4033 HAOI2015 T1 树形DP

本文详细介绍了如何解决非线性树形DP问题,即在给定的树中选择指定数量的节点染成黑色,以最大化黑色点与白色点间的距离和。通过DFS遍历树结构并使用动态规划计算最优解。

题目大意:给定一棵树,你需要把其中的 k 个点染成黑色,使得黑色点两两之间的距离和+白色点两两之间的距离和最大,求最大值
题解戳这里 Orz ydcydc
看来我对于非线性的树形DP还是做得太少了QwQ

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 2020
using namespace std;
struct edge{
    int to,f,next;
}table[M<<1];
int head[M],tot;
int n,k;
int size[M];
long long f[M][M];
//f[i][j]表示以i为根的子树中选择了j个黑点的最大贡献值
void Add(int x,int y,int z)
{
    table[++tot].to=y;
    table[tot].f=z;
    table[tot].next=head[x];
    head[x]=tot;
}
void Tree_DP(int x,int from)
{
    int i,j,k;
    size[x]=1;
    for(i=head[x];i;i=table[i].next)
        if(table[i].to!=from)
        {
            Tree_DP(table[i].to,x);
            for(j=size[x];~j;j--)
            {
                for(k=1;k<=size[table[i].to];k++)
                    f[x][j+k]=max(f[x][j+k],f[x][j]+f[table[i].to][k]+(long long)k*(::k-k)*table[i].f+(long long)(size[table[i].to]-k)*(n-::k-size[table[i].to]+k)*table[i].f );
                f[x][j]=f[x][j]+f[table[i].to][0]+(long long)size[table[i].to]*(n-::k-size[table[i].to])*table[i].f;
            }
            size[x]+=size[table[i].to];
        }
}
int main()
{
    int i,x,y,z;
    cin>>n>>k;
    for(i=1;i<n;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        Add(x,y,z);Add(y,x,z);
    }
    Tree_DP(1,0);
    cout<<f[1][k]<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值