换根dp,一般用来解决在无根树上,需要以每个节点为根跑一边dfs的dp问题

我们做两遍dfs

先钦定任意一个点为根

第一遍,算出\(f_i\)表示\(i\)的子树产生的答案,这里,子树指的是以我们钦定的那个点为根的有根树上的子树

这是从下向上的转移,也是一般树上dp的常规操作

第二遍,我们要算出真正的答案

这次是对于无根树中的子树,在第一遍dfs中,\(f_i\)已经包含了\(i\)所有“向下”的子树的贡献,那剩下的一棵子树是以它为根并向上连向它父亲的

设\(i\)的父亲是\(fa\)

这个子树的贡献是\(ans_{fa}\)减去节点\(i\)和它“向下”的子树对\(ans_{fa}\)的贡献(\(i\)的贡献已经在第一遍算进去了,所以这遍做的其实是以\(fa\)为根的计算)

也就是\(ans_{fa}-f_i\)

那么我们只需要将\(ans_i=f_i+ans_{fa}-f_i\)

上面那个式子看起来有点傻,但其中的-和+只是代表了将某些某些节点的贡献“去掉”和“加上”的方法,具体在每个题一般是不同的

当然\(+f_i\)和\(-f_i\)也不一定就能消掉(能消掉就不用换根dp了

这一遍是从上向下转移的过程


那么我们来看这个题

给定一棵\(n\)个节点无根树,每个节点有一个颜色,黑或白,黑色记为0,白色记为1

对于每个节点\(u\),选出一个包含\(u\)的连通子图,设子图中白点个数为\(cnt_1\),黑点个数为\(cnt_2\),请最大化\(cnt_1 - cnt_2\)

 

我们再代码中将黑色记为-1,白色记为1

很显然:

\[f_i=a_i+\sum_{v\subset son_i}max(f_v,0)
\]

\(a_i\)就是\(i\)号点的颜色

那么可以根据上文的讲解得出:

\[ans_i=f_i+max(ans_{fa}-max(f_i,0),0)
\]

所以得出代码:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#define reg register
#define EN std::puts("")
#define LL long long
inline int read(){
int x=0,y=1;
char c=std::getchar();
while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
return y?x:-x;
}
int n;
struct data{
int cnt0,cnt1,ans;
};
int ans[200006],f[200006],a[200006];
int fir[200006],nex[400006],to[400006],tot;
inline void add(int x,int y){
to[++tot]=y;
nex[tot]=fir[x];fir[x]=tot;
}
void dfs1(int x,int fa){
f[x]=a[x];
for(reg int v,i=fir[x];i;i=nex[i]){
v=to[i];
if(v==fa) continue;
dfs1(v,x);
f[x]+=std::max(0,f[v]);
}
}
void dfs2(int x,int fa){
if(x!=1) ans[x]=std::max(ans[fa]-std::max(0,f[x]),0)+f[x];
for(reg int i=fir[x];i;i=nex[i])if(to[i]!=fa) dfs2(to[i],x);
}
int main(){
n=read();
for(reg int i=1;i<=n;i++){
a[i]=read();
if(!a[i]) a[i]=-1;
}
for(reg int u,v,i=1;i<n;i++){
u=read();v=read();
add(u,v);add(v,u);
}
dfs1(1,1);
ans[1]=f[1];dfs2(1,1);
for(reg int i=1;i<=n;i++) std::printf("%d ",ans[i]);
return 0;
}

CF1324F Maximum White Subtree——换根dp的更多相关文章

  1. CF1324F Maximum White Subtree 题解

    原题链接 简要题意: 给定一棵树,每个点有黑白两种颜色:对每个节点,求出包含当前节点的连通图,使得白点数与黑点数差最小.输出这些值. F题也这么简单,咳咳,要是我也熬夜打上那么一场...可惜没时间打啊 ...

  2. 2018.12.19 codeforces 1092F. Tree with Maximum Cost(换根dp)

    传送门 sbsbsb树形dpdpdp题. 题意简述:给出一棵边权为1的树,允许选任意一个点vvv为根,求∑i=1ndist(i,v)∗ai\sum_{i=1}^ndist(i,v)*a_i∑i=1n​ ...

  3. CF1324 --- Maximum White Subtree

    CF1324 --- Maximum White Subtree 题干 You are given a tree consisting of \(n\) vertices. A tree is a c ...

  4. 国家集训队 Crash 的文明世界(第二类斯特林数+换根dp)

    题意 ​ 题目链接:https://www.luogu.org/problem/P4827 ​ 给定一棵 \(n\) 个节点的树和一个常数 \(k\) ,对于树上的每一个节点 \(i\) ,求出 \( ...

  5. [BZOJ4379][POI2015]Modernizacja autostrady[树的直径+换根dp]

    题意 给定一棵 \(n\) 个节点的树,可以断掉一条边再连接任意两个点,询问新构成的树的直径的最小和最大值. \(n\leq 5\times 10^5\) . 分析 记断掉一条边之后两棵树的直径为 \ ...

  6. 2018.10.15 NOIP训练 水流成河(换根dp)

    传送门 换根dp入门题. 貌似李煜东的书上讲过? 不记得了. 先推出以1为根时的答案. 然后考虑向儿子转移. 我们记f[p]f[p]f[p]表示原树中以ppp为根的子树的答案. g[p]g[p]g[p ...

  7. 换根DP+树的直径【洛谷P3761】 [TJOI2017]城市

    P3761 [TJOI2017]城市 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有ri座城市,<-1条高速公路,保证了任意两运城市之间都可以通过高速公 ...

  8. 小奇的仓库:换根dp

    一道很好的换根dp题.考场上现场yy十分愉快 给定树,求每个点的到其它所有点的距离异或上m之后的值,n=100000,m<=16 只能线性复杂度求解,m又小得奇怪.或者带一个log像kx一样打一 ...

  9. Acesrc and Travel(2019年杭电多校第八场06+HDU6662+换根dp)

    题目链接 传送门 题意 两个绝顶聪明的人在树上玩博弈,规则是轮流选择下一个要到达的点,每达到一个点时,先手和后手分别获得\(a_i,b_i\)(到达这个点时两个人都会获得)的权值,已经经过的点无法再次 ...

随机推荐

  1. 初始WebApi(1)

    如果你要问我WebApi是干嘛,我只能说它是的给数据.哈哈哈哈哈,这几天也才刚刚了解了解关于WebApi的知识,今天就来谈谈吧. 1.创建WebApi项目 第一步:选择ASP.NET Web应用程序 ...

  2. protobuf总结

    1.protobuf是什么? protobuf(protocol buffers)是一种语言中立,平台无关,可扩展的序列化数据的格式,可以用于通信协议,数据存储等. protobuf 相比于xml,j ...

  3. Java第二天,类的概念,属性和方法的使用

    上文中我们已近说到过了,Java是一种面向对象的编程语言,对象是用类来创建的,就比如世界上有无数个父亲,但是他们都有一个共同的属性--男人.也就是说某个父亲这个对象属于男人这个类.类是Java必不可少 ...

  4. C语言 文件复制

    有很多人会问,学会C语言能干啥?,就只能控制台敲个数学题,做个界面都没有的贪吃蛇么? 刚开始的我,也是这样想的,但慢慢深入C语言后,我才领略到C的强大,C的万能.小到游戏破解,加解密算法,大到设备驱动 ...

  5. [ddt02篇]十年测试老鸟帮您解析:ddt结合txt,excel,csv,mysql实现自动化测试数据驱动

    一.前言: 阅读此文之前请先阅读: [ddt01篇]十年测试老鸟帮您解析:ddt数据驱动入门基础应用:https://www.cnblogs.com/csmashang/p/12679448.html ...

  6. String 对象-->replace() 方法

    1.定义和用法 replace() 方法用于字符串替换 语法: string.replace(searchvalue,newvalue) 参数: searchvalue:被替换的字符串 newvalu ...

  7. Redis对象——有序集合(ZSet)

    有序集合类型 (Sorted Set或ZSet) 相比于集合类型多了一个排序属性 score(分值),对于有序集合 ZSet 来说,每个存储元素相当于有两个值组成的,一个是有序结合的元素值,一个是排序 ...

  8. 01-css3之过渡

    一.介绍 过渡(transition)是CSS3中具有颠覆性的特征之一,我们可以在不使用 Flash 动画或 JavaScript 的情况下,当元素从一种样式变换为另一种样式时为元素添加效果,经常和 ...

  9. docx4j docx转html

    不好用,转完问题挺多,百度还找不到资料头疼.public static void docxToHtml(String fileUrl) throws Exception { String path = ...

  10. 再看CVE-2018-12613 phpmyadmin后台文件包含&&RPO攻击

    写在前面 因为看了朋友的一篇分析又回头想了想自己去年遇到的这个纠结的问题. 去年写过一篇phpmyadmin后台文件包含的文章,写的非常的草草,并没有分析的过程,只是把自己的问题记了下来.当时纠结于最 ...