1 条题解
-
0
自动搬运
来自洛谷,原作者为

LPF
看不懂黑白却听得到钟摆,去新世界冒险和内心作伴搬运于
2025-08-24 22:15:59,当前版本为作者最后更新于2020-02-15 23:45:30,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
本题解已经通过了,这次是勘误,去掉了反作弊,望管理员通过。
感谢 @void_basic_learner dalao 指出的错误。
树形DP入门题
题意描述
在一棵以1号节点为根节点的树上,有很多
纯洁的白点,BUT,突然有一个黑点出现(可能在任意位置)
它要染黑尽可能多的节点,而在一棵子树中,
只有当黑点的比例才可以染黑根节点(即整棵子树)
求x的最小值,使得整棵树中被染黑的节点数不超过个
如果你看不懂请走传送门
算法分析
一道很裸的树形DP,但思路很巧
显然本题有以下性质:
- 最坏情况下,最开始的叛徒是叶子结点
- 因为一个节点被染黑了,一起为根节点的子树将全黑,所以最终被染黑的一定是一颗子树
先设计状态:表示使得不变黑的最小
易得:也是使得变黑的最大
可知仅与以及的大小有关(这里的表示的子节点)
那么我们用表示以为根节点的子树的大小,是需要提前用dfs预处理的
显然被染黑仅必须满足以下两种情况:
- ,即的某棵子树被染黑
- ,即的被染黑足以导致的被染黑
根据以上规律可以推出如下方程:
(不会用LaTeX写公式的蒟蒻瑟瑟发抖)取是因为需要同时满足条件1和条件2, 取是因为需要答案最优
(貌似貌似到这里就结束了呢)其实还有以下三点细节需要注意:
- 对于叶子结点,显然有
- 对于当时是不需要考虑的,因为它合法,所以即使它被染黑也无所谓
- 针对上一条结论,易得,其中
然后就去快乐吧......
代码实现
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<vector> #define maxn 500050 using namespace std; int n,k,sum[maxn]; double f[maxn],ans; vector<int>v[maxn];//用vector存图笑哈哈 void dfs(int now,int fa){ sum[now]=1; for(int i=0;i<v[now].size();i++){ int to=v[now][i]; dfs(to,now); sum[now]+=sum[to]; }//dfs预处理sum[] if(sum[now]==1){f[now]=1.0;return;}//叶子结点的处理 for(int i=0;i<v[now].size();i++){ int to=v[now][i]; f[now]=max(f[now],min(f[to],(double)sum[to]/(sum[now]-1))); }//dp if(sum[now]>k) ans=max(ans,f[now]);//统计答案,注意if return; } int main(){ scanf("%d %d",&n,&k); int x; for(int i=2;i<=n;i++){ scanf("%d",&x); v[x].push_back(i); } dfs(1,0); printf("%.8lf",ans);//注意精度问题 return 0; }结语
安利my blog (光速逃...
- 1
信息
- ID
- 4975
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者