首页 > 代码库 > BZOJ 4726: [POI2017]Sabota?

BZOJ 4726: [POI2017]Sabota?

4726: [POI2017]Sabota?

Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special Judge
Submit: 301  Solved: 127
[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。

 

 

Source

鸣谢Claris上传

[Submit][Status][Discuss]

 

 

 

树形DP。

f[i]表示i节点不叛变,最大的x值。

f[u] = max { min(f[v], p[v]) | v是u的儿子 }

其中p[i]是i节点子树大小占父节点所有儿子子树大小的比例。

 

  1 #include <bits/stdc++.h>  2   3 inline int get_c(void)  4 {  5     static const int siz = 1024;  6   7     static char buf[siz];  8     static char *head = buf + siz;  9     static char *tail = buf + siz; 10  11     if (head == tail) 12         fread(head = buf, 1, siz, stdin); 13  14     return *head++; 15 } 16  17 inline int get_i(void) 18 { 19     register int ret = 0; 20     register int neg = false; 21     register int bit = get_c(); 22  23     for (; bit < 48; bit = get_c()) 24         if (bit == -)neg ^= true; 25  26     for (; bit > 47; bit = get_c()) 27         ret = ret * 10 + bit - 48; 28  29     return neg ? -ret : ret; 30 } 31  32 const int maxn = 500005; 33 const double inf = 2e18; 34  35 int n; 36 int m; 37 int edges; 38 int fa[maxn]; 39 int hd[maxn]; 40 int to[maxn]; 41 int nt[maxn]; 42  43 inline void add(int u, int v) 44 { 45     nt[edges] = hd[u]; to[edges] = v; hd[u] = edges++; 46 } 47  48 int size[maxn]; 49  50 void dfs1(int u) 51 { 52     size[u] = 1; 53      54     for (int i = hd[u]; ~i; i = nt[i]) 55         dfs1(to[i]), size[u] += size[to[i]]; 56 } 57  58 double p[maxn]; 59  60 void dfs2(int u) 61 { 62     for (int i = hd[u]; ~i; i = nt[i]) 63         dfs2(to[i]); 64          65     if (u != 1) 66         p[u] = (double)size[u] / (size[fa[u]] - 1); 67 } 68  69 double f[maxn]; 70  71 void dfs3(int u) 72 { 73     for (int i = hd[u]; ~i; i = nt[i]) 74         dfs3(to[i]); 75      76     using namespace std; 77      78     for (int i = hd[u]; ~i; i = nt[i]) 79         f[u] = max(f[u], min(p[to[i]], f[to[i]])); 80          81     if (size[u] == 1) 82         f[u] = 1.0; 83 } 84  85 signed main(void) 86 { 87     n = get_i(); 88     m = get_i(); 89      90     memset(hd, -1, sizeof(hd)); 91      92     for (int i = 2; i <= n; ++i) 93         fa[i] = get_i(), add(fa[i], i); 94          95     dfs1(1); 96      97     dfs2(1); 98      99     dfs3(1);100     101     /*102     for (int i = 1; i <= n; ++i)103         printf("%f ", p[i]);104     puts("");105     106     for (int i = 1; i <= n; ++i)107         printf("%f ", f[i]);108     puts("");109     110     for (int i = 1; i <= n; ++i)111         printf("%d ", size[i]);112     puts("");113     */114     115     double ans = 0;116     117     for (int i = 1; i <= n; ++i)118         if (size[i] > m)ans = std::max(ans, f[i]);119         120     printf("%f\n", ans);121 }

 

@Author: YouSiki

BZOJ 4726: [POI2017]Sabota?