题目链接

http://codeforces.com/problemset/problem/1324/F

题意

给你一棵树( n n n 个顶点)和一个数组 a i a_i ai​,每个顶点要不是白色( a i a_i ai​为 1 1 1 ),要不是黑色( a i a_i ai​为 0 0 0 ),问对于每个点( 设为 i i i ),包含 i i i 点的联通块中,白点和黑点的最大差值为多少 (即:max( c n t 白 − c n t 黑 cnt_{白}-cnt_{黑} cnt白​−cnt黑​) )

解析

对于树上的任意结点来说,贡献可以分为两部分,一部分是儿子给的(第一遍 dfs统计出来),一部分是父亲给的(第二遍 dfs 计算出来),所以我们可以分别考虑各自的贡献。

定义 d p [ u ] dp[u] dp[u]:表示包含 u u u 的连通块中 max( c n t 白 − c n t 黑 cnt_{白}-cnt_{黑} cnt白​−cnt黑​),我们第一遍 dfs 定根只考虑儿子的贡献 (回溯来更新),显然只要 d p [ s o n u ] > = 0 dp[son_u]>=0 dp[sonu​]>=0 才会对 u u u 有贡献,也即是 d p [ u ] = d p [ u ] + d p [ s o n u ] dp[u]=dp[u]+dp[son_u] dp[u]=dp[u]+dp[sonu​]

第二遍 dfs 自顶向下来给各点加上父亲的贡献,设 f a fa fa 为 u u u 点的父亲,如果 d p [ u ] > d p [ f a ] dp[u]>dp[fa] dp[u]>dp[fa] 则 d p [ u ] dp[u] dp[u] 应不再考虑父亲贡献,因为 若考虑父亲的贡献会使 d p [ u ] dp[u] dp[u] 更小。
但如果 d p [ u ] < d p [ f a ] dp[u]<dp[fa] dp[u]<dp[fa],我们需要分两步考虑:
(1)如果 d p [ u ] > = 0 dp[u]>=0 dp[u]>=0 说明 f a fa fa 在统计儿子贡献的时候把 u u u 包含进去了,所以 u 和 f a u和fa u和fa 是在同一连通块里。此时 d p [ u ] = d p [ f a ] dp[u]=dp[fa] dp[u]=dp[fa]
(2)如果 d p [ u ] = = − 1 dp[u]==-1 dp[u]==−1 说明 u 和 f a u和fa u和fa 不在统一连通块里,所以为了使 d p [ u ] dp[u] dp[u] 变大,此时应加上父亲贡献: d p [ u ] + = d p [ f a ] dp[u]+=dp[fa] dp[u]+=dp[fa]

思想

这其实是 树形 d p dp dp 的一种换根的思想,针对于根不定的情况,具体步骤基本就这几步:
(1)第一遍 dfs 只统计每个点儿子的贡献,一般是随意选个根,递归下去,回溯更新儿子贡献。因为回溯更新时,每次你考虑 当前结点 u u u 时, s o n u son_u sonu​ 的贡献咱已经得出了,可以拿来用。
(2)第二遍 dfs 开始考虑父亲的贡献,就是把当前结点当作根时,还差多少,就加多少,这个一般是从第一遍 dfs 选的根开始 自顶向下 在递归的过程中考虑父亲的贡献,因为每次自顶向下时,每次你考虑 当前结点 u u u 时, f a u fa_u fau​ 作为根的贡献咱已经得出了,可以拿来用。

代码

#include <bits/stdc++.h>
#define ft first
#define sd second
#define pb push_back
#define ms(x,y) memset(x,y,sizeof(x))
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int maxn=2e5+7;
const int inf=0x3f3f3f3f;
int n,m;
int a[maxn];
vector<int> g[maxn];
int dp[maxn];
//第一遍统计儿子的贡献
void dfs(int u,int fa){dp[u]=a[u];for(auto v: g[u]){if(v==fa)continue;dfs(v,u);if(dp[v]>=0)dp[u]+=dp[v];}
}
//第二遍把父亲的贡献加上
void _dfs(int u,int fa){for(auto v: g[u]){if(v==fa)continue;if(dp[u]>dp[v]){if(dp[v]>=0)dp[v]=dp[u];else dp[v]+=dp[u];}_dfs(v,u);}
}
int main() {cin>>n;for(int i=1;i<=n;i++){scanf("%d",&a[i]);if(a[i]==0)a[i]=-1;}for(int i=1,u,v;i<n;i++){scanf("%d%d",&u,&v);g[u].pb(v);g[v].pb(u);}dfs(1,0);_dfs(1,0);for(int i=1;i<=n;i++){printf("%d%c",dp[i],i==n?'\n':' ');}return 0;
}

CF 1324-F Maximum White Subtree //树形换根dp相关推荐

  1. 树形dp ---- 树形换根dp F - The Maximum Subtree

    题目链接 题目大意: 给定一颗树,求这个树的最大子树,且这个子树是一个good-tree. good-tree的定义是:每个节点可以表示成一个数值区间,而树上的边表示两个点表示的数值区间相交 解题思路 ...

  2. CodeForces - 1324F Maximum White Subtree(树形dp)

    题目链接:点击查看 题目大意:给出 n 个点组成的树,每个点都有一个颜色,非黑即白,现在问对于每个点而言,选出一个连通块,使得白色点的个数与黑色点的个数做差最大 题目分析:记录一下div3的第一次ak ...

  3. F:Maximum White Subtree(树形dp)

    Maximum White Subtree 思路 如果考虑其覆盖范围只会到其子树上,不会到其父节点上的话(假设的情况),这道题就非常好写了,就是一个简单的自底向上传递的树形dpdpdp.所以我们还要考 ...

  4. 树形(dp+换根dp)

    普通树形dp 树形dp通常围绕根节点来写状态转移方程 用一道基础的树形dp例题来具体分析: 没有上司的舞会 Ural 大学有 N 名职员,编号为 1∼N. 他们的关系就像一棵以校长为根的树,父节点就是 ...

  5. 2019长沙学院新生赛(A水,B水,C(整除分块),D水,E(巧数学),F(二分+bfs),H(换根dp),I(线段树)J(dp+倍增+lca))

    A-XOR SUM 通过简单观察得知连续四个数的异或值就是等于0,暴力找出左区间和右区间就可以了,最多跑四个单位 0^1^2^3==0   4^5^6^7=0 #include<bits/std ...

  6. 2020牛客多校第一场B虚树+质数筛+换根dp

    题目大意: 1.可以发现阶乘增长是很快的所以你要把整颗树建立出来是不实际的. 2.我们可以假设这棵树已经建出来出来了我们应该怎么搞 首先很明显是一个树形dp, 我们设dp[j],是以j为u到其他点距离 ...

  7. 小G砍树 (换根dp)

    小G砍树 给你一棵n个节点的带标号无根树.每次,你可以选择一个度数为1的节点并将它从树上移除.问总共有多少种不同的方式能将这棵树删到只剩 1 个点.两种方式不同当且仅当至少有一步被删除的节点不同. 思 ...

  8. BZOJ 2159 「国家集训队」Crash 的文明世界(第二类斯特林数,换根DP)【BZOJ计划】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目链接 https://hydro.ac/d/bzoj/p/2159 是 hydro 的 BZOJ ...

  9. 牛客多校1 - Infinite Tree(虚树+换根dp+树状数组)

    题目链接:点击查看 题目大意:给出一个无穷个节点的树,对于每个大于 1 的点 i 来说,可以向点 i / minvid[ i ] 连边,这里的 mindiv[ x ] 表示的是 x 的最小质因数,现在 ...

最新文章

  1. Google Palette算法详解以及OC化
  2. 浅析linux内核中的idr机制
  3. 解决Asp.net Mvc返回JsonResult中DateTime类型数据格式的问题
  4. Matlab化简符号表达式
  5. Leave List-Processing 新解
  6. 从微服务到 Serverless | 开源只是开始,终态远没有到来
  7. linux常用的服务配置
  8. wbepack中output.filename和output.chunkFilename
  9. 2020年上半年美团夜宵指数发展报告
  10. linux 与有什么不同
  11. pythonfor循环加2_python中for循环如何实现每次控制变量翻倍
  12. oracle scn与数据恢复,Oracle数据恢复:数据文件头的SCN与时间校验
  13. ***制作显身网络 公开销售***挑战法律界线
  14. java中对数组进行排序_如何在Java中对数组排序
  15. Pytorch实现Transformer字符级机器翻译
  16. 常用技术面试题(软件测试)
  17. 关于ideal统计代码量 statistic插件
  18. 理解同步和异步通信:以ROS的3中典型通信机制为例
  19. ubuntu 我喜欢的快捷键
  20. 解决 Safari 12 不能安装第三方扩展的问题

热门文章

  1. python从后面删除重复项_如何从Python列表中删除重复项
  2. 货拉拉2021岗位招聘内推计划开始啦
  3. 基于nodejs+vue社区互助平台- vscode项目
  4. springboot+vue+elementui社区公益志愿者服务网站java
  5. postgresql主从复制、主从切换
  6. 无须注册的云盘平台anonfile
  7. 自媒体都在用的5个素材网站,视频、音效、图片全部免费下载~
  8. 将figma的设计图上传到蓝湖
  9. 设计模式----单利模式
  10. 怎样在网上赚钱啊,小编告诉你6种赚钱方式!