zoukankan      html  css  js  c++  java
  • 【树形dp】bzoj4726: [POI2017]Sabota?

    找点概率期望的题做一做

    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。

    题目分析

    第一眼肯定是二分想法。但是好像不是很会贪心check。

    于是干脆考虑dp,从问题反面入手。先丢开叛徒总数的限制,$f[i]$表示$i$这整颗子树没叛变的最小x值。转移就是$f[i]=max{f[i],min{size_j/(size_i-1),f[j]}}$.因为子树$i$叛变的情况需要同时满足:一是子树$j$占比例超过$x$,二是子树$j$也叛变了。那么,最小的$f[i]$只会出现在它们两个的最小值中。又由于所有情况下都要保证子树$i$不叛变,所以$f[i]$这里是取max的。最后统计答案时,就是所有子树$size>k$的最大$f[i]$。

    看题还是不仔细,第一次看成“叛徒个数小于k"WA了一发。

     1 #include<bits/stdc++.h>
     2 const int eps = 1e-10;
     3 const int maxn = 500035;
     4 
     5 int n,k,tot[maxn];
     6 double ans,f[maxn];
     7 std::vector<int> a[maxn];
     8 
     9 int read()
    10 {
    11     char ch = getchar();
    12     int num = 0;
    13     bool fl = 0;
    14     for (; !isdigit(ch); ch = getchar())
    15         if (ch=='-') fl = 1;
    16     for (; isdigit(ch); ch = getchar())
    17         num = (num<<1)+(num<<3)+ch-48;
    18     if (fl) num = -num;
    19     return num;
    20 }
    21 void dfs(int x)
    22 {
    23     tot[x] = 1;
    24     for (int i=0; i<a[x].size(); i++)
    25         dfs(a[x][i]), tot[x] += tot[a[x][i]];
    26     if (tot[x]==1) f[x] = 1;
    27     else{
    28         for (int i=0; i<a[x].size(); i++)
    29             f[x] = std::max(f[x], std::min(f[a[x][i]], 1.0*tot[a[x][i]]/(tot[x]-1)));
    30     }
    31 }
    32 int main()
    33 {
    34     n = read(), k = read();
    35     for (int i=2; i<=n; i++) a[read()].push_back(i);
    36     dfs(1);
    37     for (int i=1; i<=n; i++)
    38         if (tot[i] > k) ans = std::max(ans, f[i]);
    39     printf("%.8lf
    ",ans);
    40     return 0;
    41 }

    END

  • 相关阅读:
    atitit.TokenService v3 qb1 token服务模块的设计 新特性.docx
    Atitit attilax在自然语言处理领域的成果
    Atitit 图像清晰度 模糊度 检测 识别 评价算法 原理
    Atitit (Sketch Filter)素描滤镜的实现  图像处理  attilax总结
    atitit。企业的价值观 员工第一 vs 客户第一.docx
    Atitit 实现java的linq 以及与stream api的比较
    Atitit dsl exer v3 qb3 新特性
    Atititi tesseract使用总结
    Atitit 修改密码的功能流程设计 attilax总结
    atitit.TokenService v3 qb1  token服务模块的设计 新特性.docx
  • 原文地址:https://www.cnblogs.com/antiquality/p/9820984.html
Copyright © 2011-2022 走看看