Hetao P1307 树的剖分 题解 [ 蓝 ] [ 树形 dp ] [ 贪心 ]
树的剖分:很厉害的性质题,代码也很好写。运用到了奇偶性拼凑答案的 trick。
观察
首先发现一个很重要的条件:一个点的点权只可能是 \(0,1,2\)。
这个条件开始我们可能无法用上,于是先想最后的结果应该是怎样的。
显然,我们最后取出的方案一定可以被描述为取下以某个节点为根的子树的一部分。同时,一个深度更大的点,如果能取出这样的一部分,那么先取掉这一部分一定是最优的。为啥呢,这一点和今年那道编辑字符串很像,因为如果我不取这个部分,以成全祖先取自己的部分的话,最后的结果还是 \(1\)。因此取这个部分一定不劣。
因此我们就得到了一个贪心的策略:从深度大的往深度小的选,能选则选,这样一定能保证答案最优。
那么怎么计算当前节点能不能恰好取到 \(k\) 呢?这时候我们再来看“一个点的点权只可能是 \(0,1,2\)”这个条件,很容易发现这个很像加工零件那道题分奇偶性讨论的 trick。具体而言,就是对于一个大小大于等于 \(2\) 的树,我们一定可以取下其中的某些叶子,使得整棵树权值的奇偶性不变。理由也很简单,首先 \(0\) 的叶子可以全部先摘掉,然后此时要么有 \(2\) 的点,直接摘下 \(2\) 的点即可。要么就是 \(0,2\) 都没有,只有 \(1\),那么此时叶子结点至少有 \(2\) 个(因为树上至少有一条链),这时我们可以取下这两个 \(1\) 的节点,就能让奇偶性不变的同时减少了。
因此,我们可以算出以 \(i\) 为根节点的子树中,让连通块权值为奇数时连通块的最大权值、让连通块权值为偶数时连通块的最大权值,再判断 \(k\) 对应的奇偶性的最大权值是否大于等于 \(k\) 就能判断能不能取了。
实现上,我们可以定义 \(dp_{i,0}\) 表示连通块权值为偶数时的最大权值,\(dp_{i,1}\) 表示连通块权值为奇数时的最大权值,进行如下转移:
\]
\]
注意,代码实现时这里不能直接转移,因为先转移哪一个都会导致 dp 值被覆盖,应当先用临时变量记录下转移后 dp 的值,再给 dp 数组赋值。
同时注意取了连通块后将 \(dp_{u,0}=dp_{u,1}=-inf\),切不可赋值为 \(0\),因为此时奇数的 dp 值就不成立了。初始化时也是同理,必须注意。
时间复杂度 \(O(n)\)。
代码
#include <bits/stdc++.h>
#define fi first
#define se second
#define lc (p<<1)
#define rc ((p<<1)|1)
#define eb(x) emplace_back(x)
#define pb(x) push_back(x)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using pi=pair<int,int>;
int n,k,w[100005],ans=0,dp[100005][2];
vector<int>g[100005];
void dfs(int u,int fa)
{
dp[u][w[u]&1]=w[u];
dp[u][(w[u]&1)^1]=-0x3f3f3f3f;
for(auto v:g[u])
{
if(v==fa)continue;
dfs(v,u);
int dp0=max(dp[u][0],max(dp[u][0]+dp[v][0],dp[u][1]+dp[v][1]));
int dp1=max(dp[u][1],max(dp[u][0]+dp[v][1],dp[u][1]+dp[v][0]));
dp[u][0]=dp0;
dp[u][1]=dp1;
}
if(dp[u][k&1]>=k)
{
ans++;
dp[u][0]=dp[u][1]=-0x3f3f3f3f;
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>k;
for(int i=1;i<=n;i++)cin>>w[i];
for(int i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1,0);
cout<<ans;
return 0;
}
Hetao P1307 树的剖分 题解 [ 蓝 ] [ 树形 dp ] [ 贪心 ]的更多相关文章
- [集训队作业2018]蜀道难——TopTree+贪心+树链剖分+链分治+树形DP
题目链接: [集训队作业2018]蜀道难 题目大意:给出一棵$n$个节点的树,要求给每个点赋一个$1\sim n$之内的权值使所有点的权值是$1\sim n$的一个排列,定义一条边的权值为两端点权值差 ...
- 【bzoj4027】[HEOI2015]兔子与樱花 树形dp+贪心
题目描述 很久很久之前,森林里住着一群兔子.有一天,兔子们突然决定要去看樱花.兔子们所在森林里的樱花树很特殊.樱花树由n个树枝分叉点组成,编号从0到n-1,这n个分叉点由n-1个树枝连接,我们可以把它 ...
- 51nod 1812 树的双直径 题解【树形DP】【贪心】
老了-稍微麻烦一点的树形DP都想不到了. 题目描述 给定一棵树,边权是整数 \(c_i\) ,找出两条不相交的链(没有公共点),使得链长的乘积最大(链长定义为这条链上所有边的权值之和,如果这条链只有 ...
- 洛谷p3384【模板】树链剖分题解
洛谷p3384 [模板]树链剖分错误记录 首先感谢\(lfd\)在课上调了出来\(Orz\) \(1\).以后少写全局变量 \(2\).线段树递归的时候最好把左右区间一起传 \(3\).写\(dfs\ ...
- P3384 【模板】树链剖分 题解&&树链剖分详解
题外话: 一道至今为止做题时间最长的题: begin at 8.30A.M 然后求助_yjk dalao后 最后一次搞取模: awsl. 正解开始: 题目链接. 树链剖分,指的是将一棵树通过两次遍历后 ...
- 51Nod - 1405 树的距离之和(树形DP)
1405 树的距离之和 题意 给定一棵无根树,假设它有n个节点,节点编号从1到n,求任意两点之间的距离(最短路径)之和. 分析 树形DP. 首先我们让 \(1\) 为根.要开两个数组 \(up \ d ...
- [题解](树形dp/记忆化搜索)luogu_P1040_加分二叉树
树形dp/记忆化搜索 首先可以看出树形dp,因为第一个问题并不需要知道子树的样子, 然而第二个输出前序遍历,必须知道每个子树的根节点,需要在树形dp过程中记录,递归输出 那么如何求最大加分树——根据中 ...
- 【BZOJ2286】消耗战(虚树,DFS序,树形DP)
题意:一棵N个点的树上有若干个关键点,每条边有一个边权,现在要将这些关键点到1的路径全部切断,切断一条边的代价就是边权. 共有M组询问,每组询问有k[i]个关键点,对于每组询问求出完成任务的最小代价. ...
- 【BZOJ3611】大工程(虚树,DFS序,树形DP)
题意:有一棵树,树有边权,有若干次询问,给出一些点,求: 1.这些点互相之间的距离之和 2.点对距离中的最大和最小值 n<=1000000 q<=50000并且保证所有k之和<=2* ...
- luoguP4719 【模板】动态 DP 线段树+树链剖分+矩阵乘法+动态DP
题目描述 给定一棵n个点的树,点带点权. 有m次操作,每次操作给定x,y,表示修改点x的权值为y. 你需要在每次操作之后求出这棵树的最大权独立集的权值大小. 输入输出格式 输入格式: 第一行,n,m分 ...
随机推荐
- Tornado框架之项目部署(六)
知识点 supervisor配置与使用 nginx配置 目录: 部署Tornado 1. supervisor 安装 配置 启动 supervisorctl 2. nginx 部署Tornado 为了 ...
- Linux只gz文件格式压缩与解压缩
压缩成gz gzip * gzip file 具体参数可使用help查看 解压缩gz gunzip * gunzip file.gz 具体也是可以用help查看
- 【CSS样式】好看的样式千篇一律,有趣的灵魂万里挑一
input 输入框美化: https://www.jianshu.com/p/9b4b60b8d475 button 按钮美化: 1.登录框按钮 https://blog.csdn.net/wangj ...
- 使用 Jmeter进行压测
一.环境配置 因为jmeter需要java环境,所以需要下载Jdk和Jmeter.需要注意jdk的版本和jmeter的匹配问题 推荐大家观看Furion的作者百小僧的视频来学习,讲的很细 https: ...
- codeforces 1978 D. Elections
题目链接 https://codeforces.com/problemset/problem/1978/D 题意 对于每个测试用例,共有 \(n\) 个人,每个人的号码分别是 \(1,2,...,n\ ...
- 【Java高级编程】Java多线程学习笔记
Java 多线程 目录 Java 多线程 1.多线程创建 方法1:通过 继承 thread 类 方法2:通过 实现 Runnable 接口 2.线程中的相关方法 (1)设置优先级 setPrlorty ...
- shell 下 exec,source,.,bash和sh以及export得区别
exec执行命令时,不会启用新的shell进程. source和 .也不会启用新的shell进程,在当前shell中执行,设定的局部变量在执行完命令后仍然有效. bash或sh执行时,会另起一个子 ...
- checker jenkins 启动配置
chmod -R 755 bin scp target/*.jar ubuntu@x:/home/ubuntu/checker/ scp config/*.yml ubuntu@x:/home/ubu ...
- jenkins build
clean test org.jacoco:jacoco-maven-plugin:0.8.5:prepare-agent org.owasp:dependency-check-maven:5.3.0 ...
- React部署到线上Nginx环境中刷新页面后404解决方案
我们需要在Nginx的配置文件中修改以下内容(通常Nginx配置文件位置为/etc/nginx/nginx.conf): server { # ... location / { # ... # 增加下 ...