• puzzle 期望树形DP


    【题目描述】

    这里写图片描述
    【输入格式】
    这里写图片描述
    【输出格式】
    这里写图片描述
    【输入样例1】
    7
    1 2 1 1 4 4
    【输入样例2】
    12
    1 1 2 2 4 4 3 3 1 10 8
    【输出样例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
    【数据范围】
    这里写图片描述


    这道题不是很难,首先我们知道每个儿子的深度是不变的,而且每个点的开始时间只和他的爸爸和他爸爸的儿子有关,于是我们就往这方面去想.

    我们考虑一对父子关系,对于爸爸的每一个儿子,有1/2的几率在当前儿子之前被走到,所以我们可以得出:

    ans[now]=ans[x]+1+(size[x]-size[now]-1)/2.0;(爸爸的期望+1加上爸爸的所有儿子除了该点和他的子树除以2)

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    
    #define ll long long
    #define il inline
    #define db double
    
    using namespace std;
    
    il int gi()
    {
    	int x=0,y=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9')
    		{
    			if(ch=='-')
    				y=-1;
    			ch=getchar();
    		}
    	while(ch>='0'&&ch<='9')
    		{
    			x=x*10+ch-'0';
    			ch=getchar();
    		}
    	return x*y;
    }
    
    int head[1000045],cnt;
    struct edge
    {
    	int next,to;
    }e[1000045];
    
    il void add(int from,int to)
    {
    	e[++cnt].next=head[from];
    	e[cnt].to=to;
    	head[from]=cnt;
    }
    
    bool vis[100045];
    
    int size[100045];
    
    db ans[100045];
    
    void dfs1(int x)
    {
    	size[x]=1;
    	int r=head[x];
    	while(r!=-1)
    		{
    			int now=e[r].to;
    			if(!vis[now])
    				{
    					vis[now]=1;
    					dfs1(now);
    					size[x]+=size[now];
    				}
    			r=e[r].next;
    		}
    }
    
    void dfs2(int x)
    {
    	int r=head[x];
    	while(r!=-1)
    		{
    			int now=e[r].to;
    			if(!vis[now])
    				{
    					vis[now]=1;
    					ans[now]=ans[x]+1+(size[x]-size[now]-1)/2.0;
    					dfs2(now);
    				}
    			r=e[r].next;
    		}
    }
    
    int main()
    {
    	memset(head,-1,sizeof(head));
    
    	int n=gi();
    
    	int x;
    	for(int i=2;i<=n;i++)
    		{
    			x=gi();
    			add(x,i);
    		}
    	
    	vis[1]=1;
    	dfs1(1);
    
    	memset(vis,0,sizeof(vis));
    	vis[1]=1;
    	ans[1]=1.0;
    	dfs2(1);
    
    	for(int i=1;i<=n;i++)
    		printf("%.1f ",ans[i]);
    
    	return 0;
    }
    
    PEACE
  • 相关阅读:
    知识点拾遗——装饰器
    知识点拾遗——函数部分
    re模块和分组
    re模块进阶
    面向对象总结
    模块总结整理
    项目目录结构
    日志(模块logging)
    位、字节、字符 概念
    socketserver实现并发通讯
  • 原文地址:https://www.cnblogs.com/gshdyjz/p/7673893.html
Copyright © 2020-2023  润新知