首页 > 代码库 > [bzoj4726][POI2017][Sabota?] (树形dp)
[bzoj4726][POI2017][Sabota?] (树形dp)
Description
某个公司有n个人, 上下级关系构成了一个有根树。其中有个人是叛徒(这个人不知道是谁)。对于一个人, 如果他
下属(直接或者间接, 不包括他自己)中叛徒占的比例超过x,那么这个人也会变成叛徒,并且他的所有下属都会变
成叛徒。你要求出一个最小的x,使得最坏情况下,叛徒的个数不会超过k。
Input
第一行包含两个正整数n,k(1<=k<=n<=500000)。
接下来n-1行,第i行包含一个正整数p[i+1],表示i+1的父亲是p[i+1](1<=p[i+1]<=i)。
Output
输出一行一个实数x,误差在10^-6以内都被认为是正确的。
Sample Input
9 311222373
Sample Output
0.6666666667
HINT
答案中的x实际上是一个无限趋近于2/3但是小于2/3的数
因为当x取2/3时,最坏情况下3,7,8,9都是叛徒,超过了k=3。
Source
鸣谢Claris上传
Solution
树形dp嘛。
来自popoqqq的题解:
1.我们可以证明,最坏情况下,叛徒一定是叶子节点。
即,若有一个非叶节点是叛徒,且其儿子不是叛徒,而它父亲又被策反了,那么它的儿子是叛徒从而策反父亲的机率||比例显然更优
2.我们可以得出,一人策反,全家策反,也就是一些叛徒一定在整颗子树里
对于一个点x,设f[x]为x点不被策反需要的最小的比例
那么初始态,即叶子节点f[叶]=1
对于每个非叶节点,枚举儿子,在儿子中取最大的,儿子都是叛徒的比例或儿子不是叛徒的最小值来满足此点不是叛徒
对于每个大小大于k的子树,记录答案,去最大值
代码比较简单,用记事本手写直接交就ac了
#include <stdio.h>#include <string.h>#define MaxN 500010#define MaxBuf 1<<22#define RG register#define inline __inline__ __attribute__((always_inline))#define Blue() ((S==T&&(T=(S=B)+fread(B,1,MaxBuf,stdin),S==T))?0:*S++)#define dmax(a,b) ((a)>(b)?(a):(b))#define dmin(a,b) ((a)<(b)?(a):(b))char B[MaxBuf],*S=B,*T=B;template<class Type>inline void Rin(RG Type &x){ x=0;RG int c=Blue(); for(;c<48||c>57;c=Blue()) ; for(;c>47&&c<58;c=Blue()) x=(x<<1)+(x<<3)+c-48;}bool isn_leave[MaxN];int n,sz[MaxN],m;double f[MaxN],ans;struct Pointer{ int to; Pointer *next;}*fir[MaxN],mem[MaxN],*tot=mem;inline void link(RG int x,RG int y){ isn_leave[x]=true; *++tot=(Pointer){y,fir[x]},fir[x]=tot;}void _dfs(RG int at){ sz[at]=1; for(Pointer *iter=fir[at];iter;iter=iter->next) _dfs(iter->to),sz[at]+=sz[iter->to];}void tree_dp(RG int at){ if(!isn_leave[at]) {f[at]=1.000; return;} for(Pointer *iter=fir[at];iter;iter=iter->next){ tree_dp(iter->to); f[at]=dmax(f[at],dmin(f[iter->to],(double)sz[iter->to]/(sz[at]-1))); } if(sz[at]>m) ans=dmax(ans,f[at]);}int main(){ Rin(n),Rin(m); for(RG int i=2;i<=n;i++){ RG int pa; Rin(pa); link(pa,i); } _dfs(1); tree_dp(1); printf("%.10lf\n",ans); return 0;}
[bzoj4726][POI2017][Sabota?] (树形dp)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。