• bzoj 4726 [POI2017]Sabota? 树形dp


     [POI2017]Sabota?

    Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special Judge
    Submit: 741  Solved: 314
    [Submit][Status][Discuss]

    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 3
    1
    1
    2
    2
    2
    3
    7
    3

    Sample Output

    0.6666666667

    HINT

    答案中的x实际上是一个无限趋近于2/3但是小于2/3的数

    因为当x取2/3时,最坏情况下3,7,8,9都是叛徒,超过了k=3。

    并且带头叛变的人一定是从某个叶子往上走一条链

    因为如果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时才不会叛变

     1 #include<cstring>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<iostream>
     5 #include<cmath>
     6 #include<map>
     7 
     8 #define N 500007
     9 #define ll long long
    10 using namespace std;
    11 inline ll read()
    12 {
    13     ll x=0,f=1;char ch=getchar();
    14     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    15     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    16     return x*f;
    17 }
    18 
    19 int n,k;
    20 int cnt,hed[N],rea[N<<1],nxt[N<<1];
    21 int siz[N];
    22 double f[N],ans;
    23 
    24 void add(int u,int v)
    25 {
    26     nxt[++cnt]=hed[u];
    27     hed[u]=cnt;
    28     rea[cnt]=v;
    29 }
    30 void dfs(int u)
    31 {
    32     siz[u]=1;
    33     for (int i=hed[u];i!=-1;i=nxt[i])
    34     {
    35         int v=rea[i];
    36         dfs(v);
    37         siz[u]+=siz[v];
    38     }
    39     if (hed[u]==-1) f[u]=1;
    40     else
    41     {
    42         for (int i=hed[u];i!=-1;i=nxt[i])
    43         {
    44             int v=rea[i];
    45             f[u]=max(f[u],min(1.0*siz[v]/(siz[u]-1),f[v]));
    46         }
    47     }
    48     if (siz[u]>k) ans=max(ans,f[u]);
    49 }
    50 int main()
    51 {
    52     memset(hed,-1,sizeof(hed));
    53     n=read(),k=read();
    54     for (int i=2;i<=n;i++)
    55         add(read(),i);
    56     dfs(1);
    57     printf("%.8lf
    ",ans);
    58 }
     
  • 相关阅读:
    UICollectionViewController用法
    UISegmentedControl的详细使用
    &#x开头的是什么编码呢。浏览器可以解释它。如&#20013;&#22269;等同与中文"中国"?
    Random.nextint() 和Math.random()的区别
    UIGestureRecognizer ios手势识别温习
    [工具]Mac平台开发几个网络抓包工具(sniffer)
    IOS中Json解析的四种方法
    iOS官方Sample大全
    Ubuntu 16.04安装cuda7.5 GCC
    Ubuntu中升极下载4.2内核
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8759640.html
Copyright © 2020-2023  润新知