换根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. 2017蓝桥杯等差素数(C++B组)

    题目 :                                            等差素数列 2,3,5,7,11,13,....是素数序列.类似:7,37,67,97,127,157 ...

  2. 面试官求你了,别再问我TCP的三次握手和四次挥手

    少点代码,多点头发 本文已经收录至我的GitHub,欢迎大家踊跃star 和 issues. https://github.com/midou-tech/articles 三次握手建立链接,四次挥手断 ...

  3. 在IDEA导入maven项目

    1.依次打开File—New—Module from Existing Sources...

  4. Redis cluster集群配置教程

    这里建议大家安装4.0.9版本的 1.打开Centos虚拟机,登陆. 2.通过WinSCP把Redis集群tar包上传到虚拟机里的目录里,我的目录是 /usr/local 这里我已经上传过了并解压了, ...

  5. Kitty-Cloud服务搭建过程剖析

    项目地址 https://github.com/yinjihuan/kitty-cloud 服务搭建 大家目前看到的都是我已经搭建好了的服务,如果让你从零开始自己搭建一个微服务的项目,要怎么做? 我们 ...

  6. 一、华为模拟器eNSP下载与安装教程

    简单介绍一下 eNSP: eNSP是一款由华为提供的免费的图形化网络仿真工具平台,它将完美呈现真实设备实景(包括华为最新的ARG3路由器和X7系列的交换机),支持大型网络模拟,让你有机会在没有真实设备 ...

  7. 解决从服务器获取的数组是 __NSCFConstantString以及""没有空格字符串的问题

    AJ分享,必须精品 问题 项目遇到了个bug,从服务器获取到的数据是这样的 { status = 1, data = [ { uid = 161, type = 2, id = 79, addtime ...

  8. 怎么入门python?不懂你别瞎尝试,看看大佬怎么说

    学习任何一门语言都是从入门,通过不间断练习达到熟练水准.虽然万事开头难,但好的开始是成功的一半,今天这篇文章就来谈谈怎么入门python? 在开始学习python之前,你需要确定好学习计划和方式 比如 ...

  9. vuepress+gitee 构建在线项目文档

    目录 快速入门 在现有vue项目中安装本地开发依赖vuepress 在现有vue项目根目录下创建docs目录 创建并配置文档首页内容 运行,查看效果 可能会出现vue和vue-server-rende ...

  10. 【题解】P2024 [NOI2001]食物链 - 数据结构 - 并查集

    P2024 [NOI2001]食物链 声明:本博客所有题解都参照了网络资料或其他博客,仅为博主想加深理解而写,如有疑问欢迎与博主讨论✧。٩(ˊᗜˋ)و✧*。 题目描述 动物王国中有三类动物 \(A,B ...