zoukankan      html  css  js  c++  java
  • cogs 1962. [HAOI2015]树上染色

                    ★★☆   输入文件:haoi2015_t1.in   输出文件:haoi2015_t1.out   简单对比
                        时间限制:1 s   内存限制:256 MB

    【题目描述】

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

    【输入格式】

    第一行两个整数N,K。

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

    【输出格式】

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

    【输入样例1】

    3 1

    1 2 1

    1 3 2

    【输出样例1】

    3

    【输入样例2】

    5 2

    1 2 3

    1 5 1

    2 3 1

    2 4 2

    【输出样例2】

    17

    【样例解释】

    在第二个样例中,将点1,2染黑就能获得最大收益。

    【数据范围】

    对于30%的数据,N<=20

    对于50%的数据,N<=100

    对于100%的数据,N<=2000,0<=K<=N

    题解:

      这是一道树形DP,考虑对于每一条边,它对答案的贡献值=两端的黑点个数乘积*边权+两端白点个数乘积*边权。

      令f[i][j]表示以i为根的子树中,有j个黑点的最大收益。对于某一个节点x及其某一儿子y,考虑x与y的连边对答案的贡献,我们可以先枚举x中的黑点个数,再枚举y的黑点个数,用类似01背包来转移。

     1 /**************************************************************
     2     Problem: 4033
     3     User: __abcdef__
     4     Language: C++
     5     Result: Accepted
     6     Time:6824 ms
     7     Memory:32932 kb
     8 ****************************************************************/
     9  
    10 #include<iostream>
    11 #include<cstdio>
    12 #include<cstdlib>
    13 #include<cstring>
    14 #include<cmath>
    15 #include<algorithm>
    16 #include<queue>
    17 #include<vector>
    18 using namespace std;
    19 typedef long long LL;
    20 const LL inf=1e15,maxn=2010;
    21 LL N,K;
    22 vector<LL> to[maxn],cost[maxn];
    23 LL fa[maxn],f[maxn][maxn],siz[maxn];
    24 inline void dfs(LL x,LL fath){
    25     fa[x]=fath; siz[x]=1;
    26     for(int i=0;i<to[x].size();i++){
    27         LL y=to[x][i];
    28         if(y!=fath){
    29             dfs(y,x);
    30             siz[x]+=siz[y];
    31         }
    32     }
    33 }
    34  
    35 inline void calc(LL x){//计算以x为根的情况 
    36     f[x][0]=0; f[x][1]=0;
    37     if(siz[x]==1) return ;//叶子节点
    38     for(int i=0;i<to[x].size();i++){//枚举子树 
    39         LL y=to[x][i],val=cost[x][i]; 
    40         if(y!=fa[x]){
    41             calc(y);
    42             for(int tot=min(K,siz[x]);tot>=0;tot--){//枚举以x为根的子树中有几个黑点  
    43                 for(int j=0;j<=min(siz[y],K)&&j<=tot;j++){//这个子树中有多少黑点 
    44                     LL ans1=(LL)j*(K-(LL)j)*val;
    45                     LL ans2=(siz[y]-(LL)j)*(N-K-(siz[y]-(LL)j))*val;
    46                     LL tmp=f[y][j]+ans1+ans2;
    47                     f[x][tot]=max(f[x][tot],f[x][tot-j]+tmp);   
    48                 }
    49             }
    50         }
    51     }
    52 }
    53  
    54 int main(){
    55     scanf("%lld%lld",&N,&K);
    56     for(int i=1;i<=N-1;i++){
    57         LL u,v,c;
    58         scanf("%lld%lld%lld",&u,&v,&c);
    59         to[u].push_back(v); cost[u].push_back(c);
    60         to[v].push_back(u); cost[v].push_back(c);
    61     }
    62     for(int i=1;i<=N;i++){
    63         for(int j=1;j<=N;j++){
    64             f[i][j]=-inf;
    65         }
    66     }
    67     dfs(1,-1);
    68     calc(1);
    69     printf("%lld
    ",f[1][K]);
    70     return 0;
    71 }
  • 相关阅读:
    最后之作-Last Order(bushi
    Hydra's plan
    CSP-S2019游记
    题解 P1407
    初赛排序知识
    题解 洛谷P3469
    二分图网络流知识总结
    题解 SGU294 He's Circles
    noip复习——逆元
    noip复习——线性筛(欧拉筛)
  • 原文地址:https://www.cnblogs.com/CXCXCXC/p/5399697.html
Copyright © 2011-2022 走看看