CF1324F Maximum White Subtree——换根dp
换根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
很显然:
\]
\(a_i\)就是\(i\)号点的颜色
那么可以根据上文的讲解得出:
\]
所以得出代码:
#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的更多相关文章
- CF1324F Maximum White Subtree 题解
原题链接 简要题意: 给定一棵树,每个点有黑白两种颜色:对每个节点,求出包含当前节点的连通图,使得白点数与黑点数差最小.输出这些值. F题也这么简单,咳咳,要是我也熬夜打上那么一场...可惜没时间打啊 ...
- 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 ...
- CF1324 --- Maximum White Subtree
CF1324 --- Maximum White Subtree 题干 You are given a tree consisting of \(n\) vertices. A tree is a c ...
- 国家集训队 Crash 的文明世界(第二类斯特林数+换根dp)
题意 题目链接:https://www.luogu.org/problem/P4827 给定一棵 \(n\) 个节点的树和一个常数 \(k\) ,对于树上的每一个节点 \(i\) ,求出 \( ...
- [BZOJ4379][POI2015]Modernizacja autostrady[树的直径+换根dp]
题意 给定一棵 \(n\) 个节点的树,可以断掉一条边再连接任意两个点,询问新构成的树的直径的最小和最大值. \(n\leq 5\times 10^5\) . 分析 记断掉一条边之后两棵树的直径为 \ ...
- 2018.10.15 NOIP训练 水流成河(换根dp)
传送门 换根dp入门题. 貌似李煜东的书上讲过? 不记得了. 先推出以1为根时的答案. 然后考虑向儿子转移. 我们记f[p]f[p]f[p]表示原树中以ppp为根的子树的答案. g[p]g[p]g[p ...
- 换根DP+树的直径【洛谷P3761】 [TJOI2017]城市
P3761 [TJOI2017]城市 题目描述 从加里敦大学城市规划专业毕业的小明来到了一个地区城市规划局工作.这个地区一共有ri座城市,<-1条高速公路,保证了任意两运城市之间都可以通过高速公 ...
- 小奇的仓库:换根dp
一道很好的换根dp题.考场上现场yy十分愉快 给定树,求每个点的到其它所有点的距离异或上m之后的值,n=100000,m<=16 只能线性复杂度求解,m又小得奇怪.或者带一个log像kx一样打一 ...
- Acesrc and Travel(2019年杭电多校第八场06+HDU6662+换根dp)
题目链接 传送门 题意 两个绝顶聪明的人在树上玩博弈,规则是轮流选择下一个要到达的点,每达到一个点时,先手和后手分别获得\(a_i,b_i\)(到达这个点时两个人都会获得)的权值,已经经过的点无法再次 ...
随机推荐
- MTK Android Camera运行流程
Android Camera 运行流程 总体架构1.CameraService服务的注册2.Client端的应用层到JNI层Camera App-JNI3.Client到Service的连接4.HAL ...
- MySQL入门,第三部分,学会添加删除数据库
一.建立数据库 create database [if not exists] database_name [create_specification] 注意: 1.if not exists === ...
- C语言 文件操作(五)
(1)size_t fread ( void * ptr, size_t size, size_t count, FILE * stream ); 其中,ptr:指向保存结果的指针:size:每个数据 ...
- flask 入门之 logging
如想看详细说明,请到: 1.https://www.cnblogs.com/yyds/p/6901864.html 2.https://docs.python.org/2/library/loggin ...
- 【python】利用jieba中文分词进行词频统计
以下代码对鲁迅的<祝福>进行了词频统计: import io import jieba txt = io.open("zhufu.txt", "r" ...
- 中阶d03.3 JDBC_CURD_Util --- 使用 junit执行单元测试(增删改查)
1.单元测试环境准备 https://www.cnblogs.com/longesang/p/11399010.html 2.测试 3.结果返回 4.代码 新建一个test目录统一存放测试案例 查: ...
- Python设计模式(4)-装饰模式
# coding=utf-8 # * 一般情况下,当一个基类写好之后,我们也许不愿意去改动,也不能改动,原因是# * 这样的在项目中用得比较久的基类,一旦改动,也许会影响其他功能模块,但是,# * 又 ...
- 数据结构和算法(Golang实现)(18)排序算法-前言
排序算法 人类的发展中,我们学会了计数,比如知道小明今天打猎的兔子的数量是多少.另外一方面,我们也需要判断,今天哪个人打猎打得多,我们需要比较. 所以,排序这个很自然的需求就出来了.比如小明打了5只兔 ...
- 009-数组-C语言笔记
009-数组-C语言笔记 学习目标 1.[掌握]数组的声明 2.[掌握]数组元素的赋值和调用 3.[掌握]数组的初始化 4.[掌握]数组的遍历 5.[掌握]数组在内存中的存储 6.[掌握]数组长度计算 ...
- Redis linux 下安装
Redis linux 下安装 下载Redis安装包,可以从Redis中文网站中下载 下载地址:http://www.redis.cn/download.html Redis4.0 稳定版本 使用&l ...