您的位置:首页 > 其它

【NOIP2016提高A组模拟7.17】寻找

2016-07-17 12:28 501 查看

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的期望值。

Input

第一行一个数N,表示节点数

第二行N-1个数,第i个数表示节点i+1的父节点(保证parent[i]

Output

一行N个小数,第i个数表示starting_time[i]的期望值,保留一位小数。

Sample Input

输入1:

7

1 2 1 1 4 4

输入2:

12

1 1 2 2 4 4 3 3 1 10 8

Sample Output

输出1:

1.0 4.0 5.0 3.5 4.5 5.0 5.0

输出2:

1.0 5.0 5.5 6.5 7.5 8.0 8.0 7.0 7.5 6.5 7.5 8.0

Data Constraint

对于30%的数据,N<=1000

对于100%的数据,N<=100000

Hint

样例解释:

样例1共12种遍历方法,依次如下

1 2 3 4 6 7 5

1 2 3 4 7 6 5

1 2 3 5 4 6 7

1 2 3 5 4 7 6

1 4 6 7 2 3 5

1 4 7 6 2 3 5

1 4 6 7 5 2 3

1 4 7 6 5 2 3

1 5 2 3 4 6 7

1 5 2 3 4 7 6

1 5 4 6 7 2 3

1 5 4 7 6 2 3

Solution

与昨天一样,神题!!!看看这里

另外,某人昨天第一题光看样例就看出了100分

今天接着看样例,又是100分!

对于每个点,它的值就是所有兄弟的子树大小/2+父亲的值+1

自己推一下,多设几个东西表示,再化简就变成了上面的式子

Code

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define N 101000
using namespace std;
int n,fa
,size
,last[N*10],next[N*10],to[N*10],tot=0;
double a
;
void putin(int x,int y)
{
next[++tot]=last[x];last[x]=tot;to[tot]=y;
}
void dg(int x)
{
size[x]=1;for(int i=last[x];i;i=next[i]) dg(to[i]),size[x]+=size[to[i]];
}
void dg2(int x)
{
for(int i=last[x];i;i=next[i])
{
a[to[i]]=(double)(size[x]-size[to[i]]-1)/2+a[x]+1;
dg2(to[i]);
}
}
int main()
{
scanf("%d",&n);fo(i,2,n) scanf("%d",&fa[i]),putin(fa[i],i);
dg(1);a[1]=1.0;dg2(1);
fo(i,1,n) printf("%.1lf ",a[i]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: