BZOJ 4726: [POI2017]Sabota?
4726: [POI2017]Sabota?
Time Limit: 20 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 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
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
树形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