zoukankan      html  css  js  c++  java
  • [HAOI2015]树上染色 树状背包 dp

    #4033. [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染黑就能获得最大收益。

    Hint

    2017.9.12新加数据一组 By GXZlegend


     

     

    Source

    鸣谢bhiaibogf提供

    SolutionSolution

    #include<ctime>
    #include<cstdio>
    #include<cstdlib>
    #define min(a,b) (a<b?a:b)
    #define max(a,b) (a>b?a:b)
    const int N=2000+5;
    const int M=N<<1;
    typedef long long ll;
    int tot,to[M],val[M],next[M],head[N],size[N];bool vis[N];
    int n,K;ll f[N][N];
    inline void add(int x,int y,int z){
        to[++tot]=y;val[tot]=z;next[tot]=head[x];head[x]=tot;
    }
    void dp(int x){
        int y,w,p,q;
        size[x]=1;vis[x]=1;
        for(int i=head[x];i;i=next[i]){
            if(vis[y=to[i]]) continue;
            dp(y);
            w=val[i];
            p=min(size[x],K);
            q=min(size[y],K);//常数优化 
            for(int j=p;~j;j--){
                for(int k=q;~k;k--){
                    ll tv=1LL*(k*(K-k)+(n-size[y]-K+k)*(size[y]-k))*w;
                    f[x][j+k]=max(f[x][j+k],f[x][j]+f[y][k]+tv);
                }
            }
            size[x]+=size[y];//常数优化 
        } 
    }
    int main(){
        srand(time(0));srand(rand());
        scanf("%d%d",&n,&K);K=min(K,n-K);
        for(int i=1,x,y,z;i<n;i++) scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z);
        int root=rand()%n+1;//常数优化 
        dp(root);
        printf("%lld",f[root][K]);
        return 0;
    }

    参考:

    https://acxblog.site/archives/sol-bzoj-4033.html

    https://blog.csdn.net/Diogenes_/article/details/81044483

    https://www.cnblogs.com/leom10/p/11199602.html

  • 相关阅读:
    DapperExtensions 使用教程
    C#事件订阅及触发例子
    01、类与结构的区别
    内网信息搜集
    Anydesk拿下远程桌面
    C++对注册表的操作
    Linux下常见流编辑器的使用
    Typecho1.1反序列化漏洞复现
    Nmap脚本编写
    Github学习
  • 原文地址:https://www.cnblogs.com/shenben/p/11603476.html
Copyright © 2011-2022 走看看