• bzoj 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染黑就能获得最大收益。

     

    题解:

    小小套路题,我们要想办法简化状态,我们如果简单dp,需要知道选的白点和黑点分别是什么.

    但是我们可以改变成求每一条边对答案贡献多少

    同样地,f[i][j]表示i的子树中,选了j个黑点,对答案的最大贡献,这样就没了后效性.

    已知i子树中选了j个黑点,那么其他的黑点必然在i的上方,且必然经过i到fa[i]上边,所以这条边贡献直接乘以j*(m-j)即可,白点同理

     1 #include <algorithm>
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 #define RG register
     8 #define il inline
     9 using namespace std;
    10 typedef long long ll;
    11 const int N=4005;
    12 int n,m,num=0,nxt[N<<1],to[N<<1],dis[N<<1],head[N];ll f[N][N];
    13 void addedge(int x,int y,int z){
    14     nxt[++num]=head[x];to[num]=y;
    15     dis[num]=z;head[x]=num;
    16 }
    17 int sz[N];
    18 void dfs(int x,int last){
    19     RG int u;ll val,tmp;
    20     sz[x]=1;
    21     for(RG int i=head[x];i;i=nxt[i]){
    22         u=to[i];
    23         if(u==last)continue;
    24         dfs(u,x);
    25         for(int j=min(sz[x],m);j>=0;j--){
    26             for(int k=min(m-j,sz[u]);k>=0;k--){
    27                 val=(ll)k*(m-k)*dis[i]+(ll)(sz[u]-k)*(n-m-(sz[u]-k))*dis[i];
    28                 tmp=f[x][j]+f[u][k]+val;
    29                 if(tmp>f[x][k+j])f[x][j+k]=tmp;
    30             }
    31         }
    32         sz[x]+=sz[u];
    33     }
    34 }
    35 void work()
    36 {
    37     int x,y,z;
    38     scanf("%d%d",&n,&m);
    39     for(int i=1;i<n;i++){
    40         scanf("%d%d%d",&x,&y,&z);
    41         addedge(x,y,z);addedge(y,x,z);
    42     }
    43     dfs(1,1);
    44     printf("%lld
    ",f[1][m]);
    45 }
    46 int main()
    47 {
    48     work();
    49     return 0;
    50 }
  • 相关阅读:
    浅读《构建之法》
    def 和 lamdba的区别
    Numpy和Pandas的区别
    Django:每点击一次就增加行可输入的表格
    F函数和Q函数的作用
    super()的用法
    liunx操作系统
    celery(超详细)
    celery
    FastDFS环境搭建
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7327975.html
Copyright © 2020-2023  润新知