zoukankan      html  css  js  c++  java
  • BZOJ4033 HAOI2015 树上染色 【树上背包】

    BZOJ4033 HAOI2015 树上染色


    Description

    有一棵点数为N的树,树边有边权。给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并将其他的N-K个点染成白色。将所有点染色后,你会获得黑点两两之间的距离加上白点两两之间距离的和的收益。
    问收益最大值是多少。

    Input

    第一行两个整数N,K。
    接下来N-1行每行三个正整数fr,to,dis,表示该树中存在一条长度为dis的边(fr,to)。
    输入保证所有点之间是联通的。
    N<=2000,0<=K<=N

    Output

    输出一个正整数,表示收益的最大值。

    Sample Input

    5 2
    1 2 3
    1 5 1
    2 3 1
    2 4 2

    Sample Output

    17
    【样例解释】
    将点1,2染黑就能获得最大收益。



    using namespace std;
    #define N 2010
    #define LL long long
    struct Edge{LL v,w,next;}E[N<<1];
    LL dp[N][N],siz[N];
    LL n,k,tot=0,head[N];
    void add(LL u,LL v,LL w){
        E[++tot]=(Edge){v,w,head[u]};
        head[u]=tot;
    }
    void dfs(LL u,LL fa){
        siz[u]=1;
        for(LL i=head[u];i;i=E[i].next){
            LL v=E[i].v;
            if(v==fa)continue;
            dfs(v,u);
            for(LL j=min(siz[u]+siz[v],k);j>=0;j--)
                for(LL l=max(0LL,j-siz[u]);l<=min(j,siz[v]);l++)
                    dp[u][j]=max(dp[u][j],dp[u][j-l]+dp[v][l]+1LL*E[i].w*(l*(k-l)+(siz[v]-l)*(n-k-siz[v]+l)));
            siz[u]+=siz[v];
        }
    }
    int main(){
        scanf("%lld%lld",&n,&k);
        for(LL i=1;i<n;i++){
            LL u,v,w;scanf("%lld%lld%lld",&u,&v,&w);
            add(u,v,w);
            add(v,u,w);
        }
        dfs(1,0);
        printf("%lld",dp[1][k]);
        //system("pause");
        return 0;
    }
    
    这里写代码片
  • 相关阅读:
    base64 转blob,base64 转文件
    下载附件时防止连点
    windows更新失败
    ValidationError: webpack Dev Server Invalid Options
    导入,导出
    软件的结构
    VueRouter(一)
    根据IP判断所在地区
    phpcms v9 非超级管理员 发布不了内容的解决办法
    VIM 快捷键
  • 原文地址:https://www.cnblogs.com/dream-maker-yk/p/9676329.html
Copyright © 2011-2022 走看看