【Codeforces 696B】【JZOJ 4647】寻找

来源:互联网 发布:mysql hadoop实时同步 编辑:程序博客网 时间:2024/05/03 14:07

Description

他们度蜜月的地方是一棵树,共有N个节点,Bob会使用下列DFS算法对该树进行遍历。

starting_time是一个容量为n的数组current_time = 0dfs(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的期望值。

Analysis

设当前要算v的期望,已经算出了v的father的期望,把那些排列写出来,仔细观察,可以将排列按v在当前其兄弟的列表中的出现位置分类。设v及其兄弟共有n个,sum表示v的兄弟的大小和。
可以得出这样一个式子

Ans[v]=k=0n1k(n2)!sum+f[v]+1

化简之后就成了
Ans[v]=Ans[father]+1+sum/2

Code

#include<cstdio>#include<algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define efo(i,v) for(int i=last[v];i;i=next[i])using namespace std;const int N=100010,M=N*2;int n,tot,to[M],next[M],last[N],size[N];double f[N];void link(int u,int v){    to[++tot]=v,next[tot]=last[u],last[u]=tot;}void dfs1(int v,int from){    size[v]=1;    efo(i,v)    {        int u=to[i];        if(u==from) continue;        dfs1(u,v);        size[v]+=size[u];    }}void dfs(int v,int from){    efo(i,v)    {        int u=to[i];        if(u==from) continue;        f[u]=f[v]+1+(size[v]-1-size[u])/2.0;        dfs(u,v);    }}int main(){    int x;    scanf("%d",&n);    fo(i,2,n)    {        scanf("%d",&x);        link(i,x),link(x,i);    }    dfs1(1,0);    f[1]=1;    dfs(1,0);    fo(i,1,n) printf("%.1lf ",f[i]);    return 0;}
0 0
原创粉丝点击