bzoj4726【POI2017】Sabota?
首先可以推出来如果i没有带头叛变,那么i的父亲也一定不会带头叛变,证明显然
所以最劣情况初始的叛徒肯定是叶子,并且带头叛变的人一定是从某个叶子往上走一条链
f[i]表示i不带头叛变的话最小的x
那么我们对所有子树大小>k的f值取max即是答案
f[i]=max j为i的儿子 (min(f[j],siz[j]/(siz[i]-1))
因为对于i的一个儿子j,假如i因为j的子树里的叛徒比例大于x而带头叛变,那么既要满足x<=(j的子树大小占i的子树大小的比例),还要满足j带头叛变即x<=f[j],所以对两个量取min
那么如果i不叛变,那么就不能满足任意一个条件,所以对所有的取max
对于叶子,f[i]=1,因为不管怎样叶子本身就是叛徒,可以视为不需要条件就可以带头叛变,即只有当x>1时才不会叛变
某神犇博客:http://blog.csdn.net/neither_nor/article/details/53373065
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; const int Mx=500010; int n,k,tot,head[Mx],next[Mx],ver[Mx],siz[Mx]; double f[Mx],ans; inline void add(int x,int y) { next[++tot]=head[x]; ver[tot]=y; head[x]=tot; } void dfs(int x) { siz[x]=1; for(int i=head[x];i;i=next[i]) { int y=ver[i]; dfs(y); siz[x]+=siz[y]; } if(!head[x]) f[x]=1; if(head[x]) for(int i=head[x];i;i=next[i]) { int y=ver[i];f[x]=max(f[x],min(1.0*siz[y]/(siz[x]-1),f[y])); } if(siz[x]>k) ans=max(ans,f[x]); } int main() { scanf("%d%d",&n,&k); for(int i=2;i<=n;i++) { int a;scanf("%d",&a); add(a,i); } dfs(1); printf("%.8lf\n",ans); return 0; }