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. 如何设计一个web容器

    开发一个web容器涉及很多不同方面不同层面的技术,例如通信层的知识,程序语言层面的知识等等,且一个可用的web容器是一个比较庞大的系统,要说清楚需要很长的篇幅,本文旨在介绍如何设计一个web容器,只探 ...

  2. 【一天一道LeetCode】#44. Wildcard Matching

    一天一道LeetCode系列 (一)题目 Implement wildcard pattern matching with support for '?' and '*'. '?' Matches a ...

  3. JavaScript进阶(二)在一个JS文件中引用另一个JS文件

    在一个JS文件中引用另一个JS文件       转载地址:http://blog.csdn.net/zndxlxm/article/details/7875787 方法一 在调用文件的顶部加入下例代码 ...

  4. DOS窗口如何实现复制粘贴

    最近很多时候直接ctrl+c和ctrl+v无法实现DOS中的复制与粘贴,自己输入很麻烦.就要选择其他方式.查找资源后,总结如下: 方法一:第一种方式:右键标记-->选中-->标题栏右键编辑 ...

  5. Erlang cowboy routing 路由

    Erlang cowboy routing 路由 本文译自: http://ninenines.eu/docs/en/cowboy/1.0/guide/routing/ Routing 默认情况下,C ...

  6. Aandroid 图片加载库Glide 实战(一),初始,加载进阶到实践

    原文: http://blog.csdn.net/sk719887916/article/details/39989293 skay 初识Glide 为何使用 Glide? 有经验的 Android ...

  7. Android Studio 错误 Duplicate files copied in APK META-INF/LICENSE.txt解决方案

    My logcat: log Execution failed for task ':Prog:packageDebug'. Duplicate files copied in APK META-IN ...

  8. IOS9关于搜索的认识和实现

    原文链接 : iOS 9 App Search Tutorial: Introduction to App Search 原文作者 : Chris Wagner 译文出自 : 开发技术前线 www.d ...

  9. nasm预处理器(4)

    nasm定义了一套标准宏,当开始处理源文件时,这些宏都已经被定义了,如果希望程序在执行前没有预定义的宏存在,可以使用%clear清空预处理器的一切宏. __NASM_MAJOR__ 主版本号 __NA ...

  10. LeetCode(50)-Word Pattern

    题目: Given a pattern and a string str, find if str follows the same pattern. Here follow means a full ...