题目描述

离线题库请

题目描述

某个公司有\(n\)个人, 上下级关系构成了一个有根树。其中有个人是叛徒(这个人不知道是谁)。对于一个人, 如果他

下属(直接或者间接, 不包括他自己)中叛徒占的比例超过\(x\),那么这个人也会变成叛徒,并且他的所有下属都会变

成叛徒。你要求出一个最小的\(x\),使得最坏情况下,叛徒的个数不会超过\(k\)。

输入格式

第一行包含两个正整数\(n,k(1<=k<=n<=500000)\)。

接下来\(n-1\)行,第\(i\)行包含一个正整数\(p[i+1]\),表示\(i+1\)的父亲是\(p[i+1](1<=p[i+1]<=i)\)。

输出格式

输出一行一个实数\(x\),误差在\(10^-6\)以内都被认为是正确的。

自己想出来的\(QWQ\),刚开始想的是二分\(+dp\),但是最后搞出来的方程发现和题解差不多

题解

思路细想的话非常绕!!!不细想的话随便搞搞也能出来

首先考虑这么两个事儿

  1. 最坏情况一定是子节点是第一个叛徒;

    因为假如某节点\(i\)变成叛徒,他的父亲\(fa\)不会受影响,那么他的叶节点\(leaf\)变成叛徒,反而可能把以\(i\)为根的子树全变成叛徒,创造更多的叛徒,甚至把\(fa\)也变成叛徒
  2. 最坏情况一定是一棵子树全部是叛徒,而不会出现森林;

我们考虑树上\(dp\)

首先统计出子树\(i\)的大小

那么让这颗子树变成叛徒的条件是什么呢,宁先想着,我待会儿和宁说

一个子树变成叛徒的边界条件是啥呢,就是求使当前子树变成叛徒的最大\(x\),\(x\)再大一点点就不行了,我们把这个稍微大一点点的\(x\)叫做\(x_1\),而我们求的是不让子树大小大于\(k\)的\(x\)的最小值,宁想一想这俩东西的关系

可以发现我们要求的答案就是所有大小大于\(k\)的子树的\(x_1\)的最大值,又因为是稍微大一点点,所以我们想成一样大

然后就可以\(dp\)了

此时回到上面的问题,让一颗子树变成叛徒的条件就是有一棵他的儿子叛变,而且以儿子为根的子树的大小在可以整棵子树所占的比例大于等于当前节点叛变要求的\(x\)

这俩条件需要同时满足,所以我们求其中的较小值,即以下

 minn = min( dp[son], 1.0 * siz[v] / ( siz[now] - 1 ) )     // 注意乘1.0,如果( double )转高精的话取完min就会变成0,我WA了一上午

然后我们在它的每棵子树的\(minn\)中取一个最大值就是当前节点恰好叛变的\(x\),也是恰好不叛变的值

最后在每个大小大于\(k\)的子树的\(dp\)里取个最大值,就是恰好不让所有的大于\(k\)的子树叛变的\(x\)即答案

#include<bits/stdc++.h>
using namespace std;
#define rint register int
int n, k;
int b[500010];
double dp[500010], ans;
vector< int > vec[500010];
inline int read( void ){
int re = 0, f = 1; char ch = getchar();
while( ch > '9' || ch < '0' ){
if( ch == '-' ) f = -1;
ch = getchar();
}
while( ch >= '0' && ch <= '9' ){
re = re * 10 + ch - '0';
ch = getchar();
}
return re * f;
}
inline void dfs( int now ){
b[now] = 1;
for( rint i = 0; i < vec[now].size(); i++ ){
int v = vec[now][i];
dfs( v );
b[now] += b[v];
}
dp[now] = ( b[now] == 1 );
if( b[now] != 1 ){
for( rint i = 0; i < vec[now].size(); i++ ){
int v = vec[now][i];
dp[now] = fmax( dp[now], fmin( dp[v], 1.0 * b[v] / ( b[now] - 1 ) ) );
}
}
if( b[now] > k ){
ans = max( ans, dp[now] );
}
}
int main( void ){
n = read(); k = read();
for( rint i = 2; i <= n; i++ ){
int u; u = read();
vec[u].push_back( i );
}
dfs( 1 );
cout << ans;
return 0;
}

数据点下载

最新文章

  1. 数据库Sharding系列文章
  2. [WP8.1开发]RSA 使用BouncyCastle 公钥解密
  3. WPF自定义控件与样式(10)-进度控件ProcessBar自定义样
  4. 通过group by和having去除重复
  5. SAP GUI SAPLOGON.INI
  6. hibernate核心接口,和扩展接口。回顾笔记,以前没记,现在补上,纯手工敲的。
  7. linux 系统安装 mysql
  8. IE11登陆交行网银崩溃
  9. 201509020-js
  10. 热切换Log4j级别配置
  11. Nginx安装、平滑升级与虚拟机配置
  12. 03_ if 练习 _ little2big
  13. 101210-450789-147200(可以激活Xshell5,而且可以升级) 亲测可用 只能用于xshell5
  14. 利用Python测量滴水湖的水面面积
  15. scrapy之日志等级
  16. LeetCode刷题指南(字符串)
  17. scrapy之downloader执行流程
  18. JavaScript基础知识之 每日一题(网上搜罗来滴)
  19. Android Sms短信发送
  20. error C2275: &#39;SOCKET&#39; : illegal use of this type as an expression

热门文章

  1. 华为OD两轮技术面试
  2. JavaScript学习总结(三)BOM和DOM详解
  3. python爬虫心得(第一天)
  4. jquery mobile AJAX特性的陷阱
  5. 使用Commons Logging
  6. HTTP接口抓包工具之Fiddler
  7. 高阶函数---swift中的泛型介绍(一步步实现Map函数)
  8. HDU 5894 hannnnah_j&rsquo;s Biological Test【组合数学】
  9. Python 异常处理中的 esle
  10. IIS+PHP+Mysql 返回500,服务器内部资源问题