您的位置:首页 > 其它

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

2016-07-17 21:31 267 查看

题目:

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

样例输入:

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

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

7

1 2 1 1 4 4

样例输出:

1.0 4.0 5.0 3.5 4.5 5.0 5.0

数据范围:

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

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

剖解题目:

给一颗有根树以及树上点的关系,问所有遍历后的序列中,每个节点出现的位置的期望值。

思路:

期望值的题目诶,一般就是努力推推公式之类的把。

解法:

反正我对概率期望一向都不会,看来回去得恶补……

这道题,可以通过组合数和一些阶乘的方法推出公式。

公式:当前节点的期望值=父亲的期望值+(Size父亲-Size当且节点-1)/2+1。(size表示这棵子树的大小(也就是这棵子树的节点数))。

然而,我现在也不会证.

代码:

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define fo(i,a,b) for(int i=a;i<=b;i++)

using namespace std;

const int maxn=1e5+3;
int a[maxn],f[maxn][150],n,dad[maxn],num[maxn];
double ans[maxn];
bool bz[maxn];

void dfs(int x)
{
if (!f[x][0]) num[x]=1;
else {
fo(i,1,f[x][0]){
dfs(f[x][i]);
num[x]+=num[f[x][i]];
}
num[x]+=1;
}
}
int main()
{
//freopen("T1.in","r",stdin);
scanf("%d",&n);
dad[1]=1;
fo(i,1,n) {
scanf("%d",&a[i]);
f[a[i]][++f[a[i]][0]]=i+1;
dad[i+1]=a[i];
}
dfs(1);
int h=0,t=1,d[maxn];
memset(d,0,sizeof(d));
d[1]=1; ans[1]=1.0;
while (h!=t) {
++h;
int u=d[h];
if (u!=1) ans[u]=ans[dad[u]]+((double)(num[dad[u]]-num[u]-1))/2+1;
fo(i,1,f[u][0]) d[++t]=f[u][i];
}
fo(i,1,n) printf("%.1lf ",ans[i]);
//  fclose(stdin);
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  杂题 数学