这道题真是非常神仙

第一眼看到题面肯定能想到状态是\(dp[i][j]\)表示\(i\)这棵子树里染了\(j\)个黑点的最大值

最大值?

什么最大值,之后就会发现这个样子完全没有办法转移

所以我们考虑一下最后的答案长什么样子

突然感觉正着做不太好做,那就干脆反着做

如果没有分出黑点和白点,那么原来的答案,也就是树上所有任意两点之间的距离肯定是可以直接算出来的,这个可以用换根\(dp\)做到\(O(n)\)

之后我们强行制造差异,那些有了差异的点肯定就没有办法计算距离加进最后的答案了,于是我们把这部分减掉

于是答案相比刚才的减掉了

\[\sum_{i=1}^n\sum_{j=1}^ndis(i,j)=\sum_{i=1}^n\sum_{j=1}^npre_i+pre_j-2*pre_{lca}\ [col_i=1\text{且}col_j=0]
\]

\(pre\)是根路径前缀和,后面那一大坨东西就是非常熟悉的树上两点之间的距离,\(col\)是染的颜色,\(0\)表示白色,\(1\)表示黑色,\(lca\)就是\(lca(i,j)\)

首先明确一下目标,我们要最大化价值,所以我们要最小化这个柿子的值

我们仔细观察一下这个柿子,你会发现一些奇妙的规律:

**如果一个点\(i\)满足\(col_i=1\),那么\(pre_i\)就会在上面那个柿子里被计算\(n-k\)次,否则就会被计算\(k\)次

**

\(k\)就是黑点的总个数

这个自己感性理解一下就好了,就是\(\sum\)的一些基本性质

之后问题变成求

\[-2*\sum_{i=1}^n\sum_{j=1}^npre_{lca}\ [col_i=1\text{且}col_j=0]
\]

好像一脸不可求的样子,但是根据我数据结构刷多了的经验,我们可以考虑一下一个类似差分的东西

我们凑合看一下,假设在\(4\)染了一个黑,那么现在对答案的贡献应该怎么算

我们设\(s_i\)表示\(i\)这棵子树内部有多少个白点

对于这个黑点来说所有可能的\(lca\)显然只能来自从它到根的路径上

根据一个非常简单的差分思想

这个时候答案就是

\(s_4*pre_4+(s_3-s_4)*pre_3+(s_2-s_3)*pre_2+(s_1-s_2)*pre_1\)

之后愉快的拆一下再合一下,变成了

\(pre_1*s_1+s_2*(pre_2-pre_1)+s_3*(pre_3-pre_2)+s_4*(pre_4-pre_3)\)

其中\(pre_1=0\),可以不用考虑

\(pre\)是什么啊,根路径前缀和啊,\(pre_2-pre_1\)是什么啊,不就是\(2\)到\(1\)那条边的边权吗

于是答案就变成了有趣的\(s_2*w_2+s_3*w_3+s_4*w_4\),\(w_i\)表示\(i\)点到其父亲的边的长度

如果看到这里能理解这个差分的话,那么有一道水题可以去做一下,尽管这是一道数据结构题

我们重新回到最开始的那个柿子,现在的问题变成了如何合理分配黑点和白点,使得这个柿子的值最大

根据我们刚才的推导有这样几条规则

  1. 一个点\(x\)染成黑色,那么贡献是\(pre_x*(n-k)\)

  2. 一个点\(x\)染成白色,那么贡献是\(pre_x*k\)

  3. 对于每条边还应统计贡献,贡献是减掉这条边的长度乘以其下面有几个白点,同时一条边可能会被这样的方式计算多次,因为这条边下方可能有好几个黑点(其实就是下面有多少个黑点算多少次)

有了这三条规则,我们就可以很轻易的设计出状态来,用\(dp[i][j]\)表示以\(i\)为根的子树里染\(j\)个白点的最小贡献是多少

这样的话直接树形\(dp\)就好了,就是一个非常套路的树上背包

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#define re register
#define maxn 2005
#define LL long long
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
struct E
{
int v,nxt,w;
}e[maxn<<1];
int n,num,K;
int sum[maxn],head[maxn],deep[maxn];
LL f[maxn],pre[maxn],dp[maxn][maxn],tf[maxn];
inline void add_edge(int x,int y,int z)
{
e[++num].v=y;
e[num].nxt=head[x];
e[num].w=z;
head[x]=num;
}
inline int read()
{
char c=getchar();
int x=0;
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9')
x=(x<<3)+(x<<1)+c-48,c=getchar();
return x;
}
void dfs(int x)
{
sum[x]=1;
for(re int i=head[x];i;i=e[i].nxt)
if(!deep[e[i].v])
{
deep[e[i].v]=deep[x]+1;
tf[e[i].v]=e[i].w,pre[e[i].v]=pre[x]+e[i].w;
dfs(e[i].v);
sum[x]+=sum[e[i].v];
f[x]+=f[e[i].v],f[x]+=sum[e[i].v]*e[i].w;
}
}
void down(int x)
{
for(re int i=head[x];i;i=e[i].nxt)
if(deep[e[i].v]>deep[x])
{
f[e[i].v]+=f[x]-f[e[i].v]-sum[e[i].v]*e[i].w;
f[e[i].v]+=(n-sum[e[i].v])*e[i].w;
down(e[i].v);
}
}
void Redfs(int x)
{
dp[x][1]=-1*(LL)K*pre[x],dp[x][0]=-1*(LL)(n-K)*pre[x];
for(re int i=head[x];i;i=e[i].nxt)
if(deep[e[i].v]>deep[x])
{
Redfs(e[i].v);
for(re int j=min(n-K,sum[x]);j>=0;j--)
{
LL mid=-9893849389343;
for(re int p=0;p<=j;p++)
mid=max(mid,dp[x][j-p]+dp[e[i].v][p]);
//树上背包合并,这里将贡献值取反了,于是需要求最大值
dp[x][j]=mid;
}
}
for(re int j=0;j<=min(n-K,sum[x]);j++)
dp[x][j]+=2*tf[x]*j*(sum[x]-j);
}
int main()
{
n=read(),K=read();
int x,y,z;
for(re int i=1;i<n;i++)
x=read(),y=read(),z=read(),add_edge(x,y,z),add_edge(y,x,z);
deep[1]=1,dfs(1),down(1);//先换根dp求一下总答案
LL ans=0;
for(re int i=1;i<=n;i++)
ans+=f[i];//f[i]表示所有点到点i的距离和
ans>>=1ll;
if(!K)
{
std::cout<<ans;
return 0;
}
memset(dp,-20,sizeof(dp));
Redfs(1);
ans+=dp[1][n-K];
std::cout<<ans;
return 0;
}

【[HAOI2015]树上染色】的更多相关文章

  1. bzoj 4033: [HAOI2015]树上染色 [树形DP]

    4033: [HAOI2015]树上染色 我写的可是\(O(n^2)\)的树形背包! 注意j倒着枚举,而k要正着枚举,因为k可能从0开始,会使用自己更新一次 #include <iostream ...

  2. BZOJ4033: [HAOI2015]树上染色(树形DP)

    4033: [HAOI2015]树上染色 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 3461  Solved: 1473[Submit][Stat ...

  3. BZOJ4033 HAOI2015 树上染色 【树上背包】

    BZOJ4033 HAOI2015 树上染色 Description 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并将其他的N-K个点染成白 ...

  4. [BZOJ4033][HAOI2015]树上染色(树形DP)

    4033: [HAOI2015]树上染色 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2437  Solved: 1034[Submit][Stat ...

  5. 【BZOJ4033】[HAOI2015]树上染色 树形DP

    [BZOJ4033][HAOI2015]树上染色 Description 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并将其他的N-K个点染 ...

  6. BZOJ_4033_[HAOI2015]树上染色_树形DP

    BZOJ_4033_[HAOI2015]树上染色_树形DP Description 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并 将其他的 ...

  7. BZOJ 4033[HAOI2015] 树上染色(树形DP)

    4033: [HAOI2015]树上染色 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 3188  Solved: 1366[Submit][Stat ...

  8. [HAOI2015]树上染色(树形dp)

    [HAOI2015]树上染色 题目描述 有一棵点数为 N 的树,树边有边权.给你一个在 0~ N 之内的正整数 K ,你要在这棵树中选择 K个点,将其染成黑色,并将其他 的N-K个点染成白色 . 将所 ...

  9. [HAOI2015]树上染色(树上dp)

    [HAOI2015]树上染色 这种要算点对之间路径的长度和的题,难以统计每个点的贡献.这个时候一般考虑算每一条边贡献了哪些点对. 知道这个套路以后,那么这题就很好做了. 状态:设\(dp[u][i]\ ...

  10. [HAOI2015]树上染色 树状背包 dp

    #4033. [HAOI2015]树上染色 Description 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并 将其他的N-K个点染成白 ...

随机推荐

  1. nohup磁盘打满问题排查与解决

    使用nohup ... & 命令启动服务器后,磁盘满了,服务宕了,然后一步一步排查是哪个文件过大,最终定位到是nohup.out文件过大,占了40G, df -lh #磁盘容量命令 du -s ...

  2. 一:XML知识整理

    一:xml 1. xml简介 a) xml, eXtensible Markup Language, 可扩展标记语言.是一种标记语言. b) xml 是一种非常灵活的语言, 没有固定的标签, 所有的标 ...

  3. apache Header set Cache-Control

    设置静态页面的缓存最大值 在.htaccess中添加下面的代码 <FilesMatch "\.(flv|gif|jpg|jpeg|png|ico|swf)$"> Hea ...

  4. Spring------约束导入和application.xml的引入方式

    1.spring约束的导入 2.SSH常用约束 3.application.xml的引入方式 <1.通过ClassPathXmlApplicationContext引入配置文件applicati ...

  5. bzoj一句话题解

    发现好多人都在搞这个...本人也想来试试(Solved刚到70就搞这个靠不靠谱啊喂).会更新的.嗯. 1000-1029 1000 A+B problem (这个还需要一句话吗?). 1001 狼抓兔 ...

  6. 解决Cannot read property 'style' of null中样式问题

    <script type="text/javascript"> function updateTime(){ var timeNow = new Date(); var ...

  7. LintCode2016年8月8日算法比赛----中序遍历和后序遍历构造二叉树

    中序遍历和后序遍历构造二叉树 题目描述 根据中序遍历和后序遍历构造二叉树 注意事项 你可以假设树中不存在相同数值的节点 样例 给出树的中序遍历: [1,2,3] 和后序遍历: [1,3,2] 返回如下 ...

  8. python 增加矩阵行列和维数

    python 增加矩阵行列和维数 方法1 np.r_ np.c_ import numpy as np a = np.array([[1,2,3],[4,5,6],[7,8,9]]) b = np.a ...

  9. Activiti实现会签功能

    一个任务需要多个角色进行审批或者表决,根据这些审批结果来决定流程的走向.实现以上任务,activiti已经提供了支持,可以使用BPMN规范的多实例活动来实现. 1.Activiti多实例: 多实例节点 ...

  10. js 正则常用函数

    正则表达式中,需要转义的字符: * . ? + $ ^ [ ] ( ) { } | \ / let reg = /\d+/g let str = 'ad/23/dfww/454/6' 1. reg.t ...