BZOJ 4726 [POI2017]Sabota?:树形dp
题意
某个公司有 $ n $ 个人,上下级关系构成了一个有根树。其中有个人是叛徒(这个人不知道是谁)。对于一个人, 如果他下属(直接或者间接, 不包括他自己)中叛徒占的比例超过 $ x $ ,那么这个人也会变成叛徒,并且他的所有下属都会变成叛徒。你要求出一个最小的 $ x $ ,使得最坏情况下,叛徒的个数不会超过 $ k $ 。$ (1 \leq k \leq n \leq 500000) $
题解
首先有一个显然的二分做法,然而不知道为什么会被卡……
于是考虑能不能 $ O(n) $ 做。
首先有两个结论:
- 最坏情况下,最初的那一个叛徒一定是叶子结点。
- 如果一个非叶子节点叛变,则它其中的一个儿子一定叛变
所以最终所有的叛徒一定是原树中的一棵子树。
$ f[i] $ 表示要使节点 $ i $(及其下属)恰好不能叛变的最小比例 $ x $
因为所有 $ size[i] > k $ 的子树都不能叛变
所以 $ ans = max(f[i]) \quad (size[i] > k) $
然后考虑怎样求 $ f[i] $
$ f[i] $ 也等价于恰好让 $ i $ 叛变的最大比例 $ x $
对于每一个 $ i $ ,首先枚举它的哪个子树叛变了(假设是 $ j $ )
那么想让 $ i $ 叛变有两个条件:
- 比例 $ x $ 满足能够让 $ j $ 叛变
- 比例 $ x $ 满足 $ \dfrac{size[j]}{size[i] - 1} > x $
所以 $ f[i] = max(f[i], min(f[j], \dfrac{size[j]}{size[i]-1})) $
边界条件为:$ f[i] = \begin{cases} 1 \quad \text{叶子结点} \\ 0 \quad \text{非叶子节点} \end{cases} $
AC Code
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
#define MAX_N 500005
using namespace std;
int n,k;
int siz[MAX_N];
double ans=0;
double f[MAX_N];
vector<int> edge[MAX_N];
void read()
{
scanf("%d%d",&n,&k);
int x;
for(int i=2;i<=n;i++)
{
scanf("%d",&x);
edge[x].push_back(i);
}
}
void dfs(int x)
{
siz[x]=1,f[x]=(edge[x].size()==0);
for(int i=0;i<edge[x].size();i++)
{
int t=edge[x][i];
dfs(t),siz[x]+=siz[t];
}
for(int i=0;i<edge[x].size();i++)
{
int t=edge[x][i];
f[x]=max(f[x],min(f[t],siz[t]/(siz[x]-1.0)));
}
if(siz[x]>k) ans=max(ans,f[x]);
}
void work()
{
dfs(1);
printf("%.9f\n",ans);
}
int main()
{
read();
work();
}
BZOJ 4726 [POI2017]Sabota?:树形dp的更多相关文章
- BZOJ 4726: [POI2017]Sabota? 树形dp
4726: [POI2017]Sabota? 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4726 Description 某个公司有n ...
- BZOJ 4726: [POI2017]Sabota?
4726: [POI2017]Sabota? Time Limit: 20 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 301 Solved ...
- 【BZOJ4726】[POI2017]Sabota? 树形DP
[BZOJ4726][POI2017]Sabota? Description 某个公司有n个人, 上下级关系构成了一个有根树.其中有个人是叛徒(这个人不知道是谁).对于一个人, 如果他 下属(直接或者 ...
- [bzoj4726][POI2017][Sabota?] (树形dp)
Description 某个公司有n个人, 上下级关系构成了一个有根树.其中有个人是叛徒(这个人不知道是谁).对于一个人, 如果他 下属(直接或者间接, 不包括他自己)中叛徒占的比例超过x,那么这个人 ...
- BZOJ 4726 POI 2017 Sabota? 树形DP
4726: [POI2017]Sabota? Time Limit: 20 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 128 Solved ...
- Bzoj 1131[POI2008]STA-Station (树形DP)
Bzoj 1131[POI2008]STA-Station (树形DP) 状态: 设\(f[i]\)为以\(i\)为根的深度之和,然后考虑从他父亲转移. 发现儿子的深度及其自己的深度\(-1\) 其余 ...
- bzoj 2286(虚树+树形dp) 虚树模板
树链求并又不会写,学了一发虚树,再也不虚啦~ 2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 5002 Sol ...
- BZOJ 4472 [Jsoi2015]salesman(树形DP)
4472: [Jsoi2015]salesman Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 417 Solved: 192[Submit][St ...
- BZOJ 4890: [Tjoi2017]城市 树形dp
标签:树形dp,枚举,树的直径 一上来看到这个题就慌了,只想到了 $O(n^3)$ 的做法. 碰到这种题时要一步一步冷静地去分析,观察数据范围. 首先,$n\leqslant 5000$,所以可以先 ...
随机推荐
- REDO 的内容:改变向量
REDO 的内容 ---改变向量 redo的内容并不是sql语句,他是放的一些改变,叫改变向量. 数据库恢复的时候并不是执行sql语句,而是一个物理的过程,是一个数据块的覆盖.是改变数据块的大小. 可 ...
- js 实现无限加载分页(适合移动端)
一.原理:当滚动条到达底部时,执行下一页内容. 判断条件需要理解三个概念: 1.scrollHeight 真实内容的高度 2.clientHeight 视窗的高度,即在浏览器中所能看到的内 ...
- [设计模式]迭代子模式 Iterator
迭代子模式又叫做游标cursor模式,是对象的行为模式.迭代子模式可以顺序的访问一个聚集中的元素而不必暴露聚集的内部表象. 迭代子模式被广泛的应用在Java语言的API中的几个设计模式之一.在Java ...
- Mahout介绍-炼数
Mahout的中文含义:象夫
- BOM对象,math对象document对象的属性和操作和 事件的基本操作
Math对象 //该对象中的属性方法 和数学有关. abs(x) 返回数的绝对值. exp(x) 返回 e 的指数. floor(x) 对数进行下舍入. log(x) 返回数的自然对数(底为e). m ...
- CNN学习笔记:线性回归
CNN学习笔记:Logistic回归 线性回归 二分类问题 Logistic回归是一个用于二分分类的算法,比如我们有一张图片,判断其是否为一张猫图,为猫输出1,否则输出0. 基本术语 进行机器学习,首 ...
- Linux服务器内存cache清理
发现cache中占用大量内存,无free内存可用 使用如下命令清理: syncsysctl -w vm.drop_caches=1 转自:http://blog.csdn.net/sky_qing/a ...
- 使用sqoop把mysql数据导入hive
使用sqoop把mysql数据导入hive export HADOOP_COMMON_HOME=/hadoop export HADOOP_MAPRED_HOME=/hadoop cp /hive ...
- JetBrains IntelliJ IDEA 15 Ultimate Edition版本激活破解
由于JetBrains系列新版本注册激活发生了变化,所以原来的激活方式已经不能在使用. 只能用新的方式来破解了.此方式支持所有系列的新版版.包括IDEA15,PHPSTORM10,WEBSTO ...
- angularjs 的controller的三种写法
AngularJS 的controller其实就是一个方法,它有三种写法: 第一种: <pre name="code" class="javascript" ...