【JZOJ4647】寻找
2016-07-17 16:27
267 查看
Description
Bob和Alice出去度蜜月,但Alice不慎走失,Bob在伤心过后,决定前去寻找Alice。他们度蜜月的地方是一棵树,共有N个节点,Bob会使用下列DFS算法对该树进行遍历。
starting_time是一个容量为n的数组 current_time = 0 dfs(v): current_time = current_time + 1 starting_time[v] = current_time 将children[v]的顺序随机排列 (每个排列的概率相同) // children[v]v的直接儿子组成的数组 for u in children[v]: dfs(u)
1是这棵树的根,Bob会从1出发,即运行dfs(1),现在他想知道每个点starting_time的期望值。
Solution
看到这题时我一脸懵逼。于是我盯着样例,于是随便打打就水过去了。
这题我们设Fi表示i点的期望值,显然,Fsoni=Fi+一坨神奇的东西。
首先,我们可以先走一些子树,然后我们把全排列弄出来,(后面与题解相同),发现j出现在i前面的概率是12,于是j对i的贡献就为12sizej(其中sizej表示j子树的大小)。
于是从根节点往下,Fi=Ffai+sizefai−sizei−12+1
Code
#include<iostream> #include<cstdio> #include<cstdlib> #define fo(i,j,k) for(int i=j;i<=k;i++) #define fd(i,j,k) for(int i=j;i>=k;i--) #define N 100001 using namespace std; int sz ; int to ,next ,last ,num=0; void link(int x,int y) { num++; to[num]=y; next[num]=last[x]; last[x]=num; } double f ; void find(int x) { sz[x]=1; for(int i=last[x];i;i=next[i]) { int v=to[i]; find(v); sz[x]+=sz[v]; } } void dfs(int x) { for(int i=last[x];i;i=next[i]) { int v=to[i]; f[v]=f[x]+(sz[x]-sz[v]-1)*0.5+1; dfs(v); } } int main() { int n; cin>>n; fo(i,2,n) { int x; scanf("%d",&x); link(x,i); } find(1); f[1]=1; dfs(1); fo(i,1,n) printf("%.1lf ",f[i]); }
相关文章推荐
- MapReduce数据输入中InputFormat类源码解析
- 小马哥----高仿苹果6sp(主板型号W9200_WZS_2QG 6582 7月版本刷机拆机主板图与开机识别图
- Linux下autoconf和automake使用
- 【GDOI2017模拟7.17】两棵树
- Andriod基础——Adapter类
- 今年暑假不AC
- UVA 1395 Slim Span 最小生成树
- 《数据结构》2.2顺序表(sequence list)
- javascript-BOM
- Hadoop yarn任务调度策略介绍
- mysql -- 清空表(truncate)与删除数据(delete)
- 按位与、或、异或等运算方法
- 【Codeforces 678E】【JZOJ 4648】锦标赛
- 2016.7.17 夏令营 Day10
- Qt Quick<OpacityMask> 圆角图片、异形图片的合成
- Bzoj1059 [ZJOI2007]矩阵游戏
- 208. Implement Trie (Prefix Tree)
- shell 常用命令行
- 【总结】SPI
- <c:import>标签说明