1 条题解
-
0
分数二分+DFS。
容易看出是
0-1形二分。每次check里,记
f表示以f为根的子树都烂了,因为注意到烂的一定是一棵子树所有的点。初始时所有叶子标记为在DFS 回溯的时候记录一下,对于一个节点,如果所有子树中坏点数量最多的那颗子树的坏点数量除以占比大于 ,就可以令当前节点的
f然后最后记录一下 的所有结点的子树大小的最大值,判断是否<=m
然后就没了。
#include<bits/stdc++.h> using namespace std; #define ll long long vector<int> v[500005]; int sz[500005]; bool fl[500005]; void pre_dfs(int now){ sz[now]=1; for(int k:v[now]){ pre_dfs(k); sz[now]+=sz[k]; } } double p; void dfs(int now){ fl[now]=0; if(v[now].size()==0){ fl[now]=1; return; } int maxx=0; for(int k:v[now]){ dfs(k); if(fl[k]) maxx=max(maxx,sz[k]); } if(maxx*1.000000/(sz[now]-1.000000)>p){ fl[now]=1; } else{ fl[now]=0; } } int n,m; bool check(double pw){ p=pw; dfs(1); int maxx=0; for(int i=1; i<=n; i++){ maxx=max(maxx,fl[i]*1*sz[i]); } memset(fl,0,sizeof fl); return maxx<=m; } signed main(){ //cin.tie(0); //ios::sync_with_stdio(false); cin>>n>>m; for(int i=2; i<=n;i++){ int vv; scanf("%d",&vv); v[vv].push_back(i); } pre_dfs(1); double l=0.000000,r=1.000000; while(fabs(r-l)>1e-5){ double mid=(l+r)/2.0; if(check(mid)) r=mid; else l=mid; } printf("%.6lf",l); return 0; }
- 1
信息
- ID
- 727
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- 递交数
- 36
- 已通过
- 5
- 上传者