P3177 [HAOI2015]树上染色

题目描述

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

输入输出格式

输入格式:

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

输出格式:

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

说明

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


这里阐述一下我的思考方式。

首先,真的一下子想到贪心去了。前几天做了消防,觉得在树的直径上会有一些奇妙优美的性质,遂开始想办法证明。

然后考试完了还在证贪心\(emmmm\)。

解法很容易懂,但是很难想(我太蒻了)


正解是树形\(DP\)

令\(dp[i][j]\)为以\(i\)为根节点的子树中 在染了\(j\)个黑点时 所有的边再加上\(i\)头上的那个边 对整颗树 的答案贡献

有灵性就有灵性在这个整颗树上

在已经处理好子树\(v\)时,我们加入边\(E_k(u,v)\)(\(u\)为\(v\)的父亲)

则\(E_k\)的贡献即为边权\(w*\)子树\(u\)中白点个数子树\(u\)外面的数白点个数\(+w*\)子树\(u\)中黑点个数子树\(u\)外面的数黑点个数,这点不难想明白

当然,不做头顶上的边也是可以的,但很多树形\(dp\)管一下自己的脑门是比较方便的

转移时,我们对每棵子树做树上分组背包,最后在判断一下她自己头上的边


code

#include <cstdio>
#include <cstring>
#define ll long long
ll max(ll x,ll y) {return x>y?x:y;}
ll min(ll x,ll y) {return x<y?x:y;}
const int N=2001;
ll dp[N][N];
//根节点为i的子树j个点染黑所有边的最大答案
ll n,k;
struct Edge
{
    ll to,next,w;
}edge[N*2];
ll head[N],cnt=0;
void add(ll u,ll v,ll w)
{
    edge[++cnt].to=v;
    edge[cnt].next=head[u];
    edge[cnt].w=w;
    head[u]=cnt;
}
int used[N];
ll dfs(ll u,ll c)
{
    used[u]=1;
    ll size=0;
    memset(dp[u],-1,sizeof(dp[u]));
    dp[u][0]=0;
    for(ll i=head[u];i;i=edge[i].next)
    {
        ll v=edge[i].to,w=edge[i].w;
        if(!used[v])
        {
            ll si=dfs(v,w);size+=si;
            for(ll j=min(k,size);j>=0;j--)
            {
                ll r=min(j,min(si,k));
                for(ll k0=0;k0<=r;k0++)
                    if(dp[u][j-k0]!=-1)
                        dp[u][j]=max(dp[u][j],dp[u][j-k0]+dp[v][k0]);
            }
        }
    }
    size++;
    ll l=max(size+k-n,1);
    for(ll i=min(k,size);i>=l;i--)
    {
        ll cc=c*(k-i)*i+c*(n-size-k+i)*(size-i);
        dp[u][i]=max(dp[u][i],dp[u][i-1])+cc;
    }
    l=size+k-n;
    dp[u][0]+=c*(n-size-k)*size;
    return size;
}

int main()
{
    scanf("%lld%lld",&n,&k);
    ll u,v,w;
    for(ll i=1;i<n;i++)
    {
        scanf("%lld%lld%lld",&u,&v,&w);
        add(u,v,w),add(v,u,w);
    }
    dfs(1,0);
    printf("%lld\n",dp[1][k]);
    return 0;
}

细节问题:

1.分组背包转移方程为:\(dp[u][j]=max(dp[u][j],dp[u][j-k0]+dp[v][k0])\)

我们一定要判断\(dp[u][j-k0]\)的合法性

2.开\(long long\)不要吝啬空间(除非卡的太死,反正也就两倍),能看尽量就开,只开一部分在计算时真的不注意就可能丢失了或者爆了

3.背包的上下界,最好加上,不然常数一大可能会\(t\)。有的不加甚至会出现一些问题。


2018.5.15

洛谷 P3177 树上染色 解题报告的更多相关文章

  1. 洛谷 P2664 树上游戏 解题报告

    P2664 树上游戏 题目描述 \(\text{lrb}\)有一棵树,树的每个节点有个颜色.给一个长度为\(n\)的颜色序列,定义\(s(i,j)\) 为 \(i\) 到 \(j\) 的颜色数量.以及 ...

  2. 洛谷 P3177 树上染色

    题面 题目要求将k个点染成黑色,求黑点两两距离及白点两两距离,使他们之和最大. 我们可以将距离转化为路径,然后再将路径路径拆分成边,就可以记录每条边被经过的次数,直接计算即可. 很简单对吧?那么问题来 ...

  3. 洛谷P3177 树上染色

    题目 一道非常好的树形DP. 状态:\(dp[u][n]\)为u的子树选n个黑点所能得到的收益最大值. 则最终的结果就是\(dp[root][k],\)\(root\)可以为任何值,为了方便,使\(r ...

  4. 洛谷 P1783 海滩防御 解题报告

    P1783 海滩防御 题目描述 WLP同学最近迷上了一款网络联机对战游戏(终于知道为毛JOHNKRAM每天刷洛谷效率那么低了),但是他却为了这个游戏很苦恼,因为他在海边的造船厂和仓库总是被敌方派人偷袭 ...

  5. 洛谷 P4597 序列sequence 解题报告

    P4597 序列sequence 题目背景 原题\(\tt{cf13c}\)数据加强版 题目描述 给定一个序列,每次操作可以把某个数\(+1\)或\(-1\).要求把序列变成非降数列.而且要求修改后的 ...

  6. 洛谷1087 FBI树 解题报告

    洛谷1087 FBI树 本题地址:http://www.luogu.org/problem/show?pid=1087 题目描述 我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全 ...

  7. 洛谷 P4211 [LNOI2014]LCA 解题报告

    [LNOI2014]LCA 题意 给一个\(n(\le 50000)\)节点的有根树,询问\(l,r,z\),求\(\sum_{l\le i\le r}dep[lca(i,z)]\) 一直想启发式合并 ...

  8. 洛谷 P2680 运输计划 解题报告

    P2680 运输计划 题目背景 公元2044年,人类进入了宇宙纪元. 题目描述 公元2044年,人类进入了宇宙纪元. \(L\)国有\(n\)个星球,还有\(n-1\)条双向航道,每条航道建立在两个星 ...

  9. 洛谷 P2245 星际导航 解题报告

    P2245 星际导航 题目描述 sideman做好了回到Gliese 星球的硬件准备,但是sideman的导航系统还没有完全设计好.为了方便起见,我们可以认为宇宙是一张有N 个顶点和M 条边的带权无向 ...

随机推荐

  1. [Ext.Net]客户关系管理系统

    本人在企业中非专业人士,交流学习. 1.登录 2.系统主界面 3.用户与角色 3.菜单管理 4.角色与授权 5.登陆日志 6.简易工作流 7.客户分类 8.客户管理 9.报价管理 业务员反馈 报价明细 ...

  2. Linux 打开句柄限制的调整

    Linux 打开句柄限制的调整 参考文章: Linux---进程句柄限制总结(http://blog.csdn.net/jhcsdb/article/details/32338953) !! 本文内容 ...

  3. 栈的顺序存储 - 设计与实现 - API实现

    Stack基本概念 栈是一种 特殊的线性表 栈仅能在线性表的一端进行操作 栈顶(Top):允许操作的一端 栈底(Bottom):不允许操作的一端 Stack的常用操作 创建栈 销毁栈 清空栈 进栈 出 ...

  4. SpriteBuilder中音频波长超过Timeline结尾的情况

    见如下图: 注意最后一个音频波长延续到Timeline结尾之后.表明这个音频文件播放长度超过Timeline(动画)播放的长度.这是否成为一个问题要视情况而定.而在这里无所谓. 如果节点所拥有的Tim ...

  5. ffdshow 源代码分析 5: 位图覆盖滤镜(总结)

    ===================================================== ffdshow源代码分析系列文章列表: ffdshow 源代码分析 1: 整体结构 ffds ...

  6. Java进阶(十五)Java中设置session的详细解释

    Java中设置session的详细解释 简单通俗的讲session就是象一个临时的容器,用来存放临时的东西.从你登陆开始就保存在session里,当然你可以自己设置它的有效时间和页面,举个简单的例子: ...

  7. Digogo ugdx文件的制作

    The openplatform source code is in old IT FTP server at "vte/KCD/20150814/openplatform_wallace. ...

  8. jquery左右折叠框

    网站左右折叠框: <!DOCTYPE html> <html> <style> #Kefclose,#Kefopen{position:absolute;left: ...

  9. 《转》iOS 平台 Cocos2d-x 项目接入新浪微博 SDK 的坑

    最近在做一个 iOS 的 cocos2d-x 项目接入新浪微博 SDK 的时候被“坑”了,最后终于顺利的解决了.发现网上也有不少人遇到一样的问题,但是能找到的数量有限的解决办法写得都不详细,很难让人理 ...

  10. permutations(全排列)

    Given a collection of distinct numbers, return all possible permutations. For example,[1,2,3] have t ...