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 }
  • 相关阅读:
    MDX Step by Step 读书笔记(六) Building Complex Sets (复杂集合的处理) Filtering Sets
    在 Visual Studio 2012 开发 SSIS,SSAS,SSRS BI 项目
    微软BI 之SSIS 系列 在 SSIS 中读取 SharePoint List
    MDX Step by Step 读书笔记(五) Working with Expressions (MDX 表达式) Infinite Recursion 和 SOLVE_ORDER 原理解析
    MDX Step by Step 读书笔记(五) Working with Expressions (MDX 表达式)
    使用 SQL Server 2012 Analysis Services Tabular Mode 表格建模 图文教程
    MDX Step by Step 读书笔记(四) Working with Sets (使用集合) Limiting Set and AutoExists
    SQL Server 2012 Analysis Services Tabular Model 读书笔记
    Microsoft SQL Server 2008 MDX Step by Step 学习笔记连载目录
    2011新的开始,介绍一下AgileEAS.NET平台在新的一年中的发展方向
  • 原文地址:https://www.cnblogs.com/CXCXCXC/p/5399697.html
Copyright © 2011-2022 走看看