Codeforces Round #362 (Div. 1) B. Puzzles 树形dp,概率

题目链接:

http://codeforces.com/problemset/problem/696/B

题意:

一个树,dfs遍历子树的顺序是随机的。所对应的子树的dfs序也会不同。输出每个节点的dfs序的期望

思路:

http://www.cnblogs.com/01world/p/5795498.html

假设四个子节点为A,B,C,D,因为排列等可能,所以A在B前面的概率跟A在B后面的概率相等,C和D对于A而言一样。所以遍历A的时间期望就是( t(B) + t(C) + t(D) )/2 + P。其中t(B)是访问B节点及其子树所需时间,尽管是随机排列,但是B子树中的节点树是确定的,所以t(B)可以确定,P是A的父节点访问时间的期望。

转移就是  dp[v]=dp[u]+1.0 + (sz[u]-sz[v]-1)/2.0  前面一部分是从父节点u直接走到v的期望,后面是前面走过了u的其它子节点到达v的期望

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 #define MS(a) memset(a,0,sizeof(a))
 5 #define MP make_pair
 6 #define PB push_back
 7 const int INF = 0x3f3f3f3f;
 8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
 9 inline ll read(){
10     ll x=0,f=1;char ch=getchar();
11     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
12     while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
13     return x*f;
14 }
15 //////////////////////////////////////////////////////////////////////////
16 const int maxn = 1e5+10;
17
18 int n,sz[maxn];
19 vector<int> g[maxn];
20 double ans[maxn];
21
22 void dfs1(int x){
23     sz[x] = 1;
24     for(int i=0; i<(int)g[x].size(); i++){
25         int v = g[x][i];
26         dfs1(v);
27         sz[x] += sz[v];
28     }
29 }
30
31 void dfs2(int u){
32     for(int i=0; i<(int)g[u].size(); i++){
33         int v = g[u][i];
34         ans[v] = ans[u]+1 + (sz[u]-sz[v]-1)*1.0/2;
35         dfs2(v);
36     }
37 }
38
39 int main(){
40     cin >> n;
41     for(int i=2; i<=n; i++){
42         int x = read();
43         g[x].push_back(i);
44     }
45
46     dfs1(1);
47     ans[1] = 1.0;
48     dfs2(1);
49
50     for(int i=1; i<=n; i++)
51         printf("%.1f ",ans[i]);
52     puts("");
53
54
55     return 0;
56 }
时间: 2024-12-25 22:21:35

Codeforces Round #362 (Div. 1) B. Puzzles 树形dp,概率的相关文章

【转载】【树形DP】【数学期望】Codeforces Round #362 (Div. 2) D.Puzzles

期望计算的套路: 1.定义:算出所有测试值的和,除以测试次数. 2.定义:算出所有值出现的概率与其乘积之和. 3.用前一步的期望,加上两者的期望距离,递推出来. 题意: 一个树,dfs遍历子树的顺序是随机的.所对应的子树的dfs序也会不同.输出每个节点的dfs序的期望   思路: 分析一颗子树: 当前已知节点1的期望为1.0 ->anw[1]=1.0 需要通过节点1递推出节点2.4.5的期望值 1的儿子分别是2.4.5,那么dfs序所有可能的排列是6种: 1:1-2-4-5  (2.4.5节点的

Codeforces Round #362 (Div. 2) C. Lorenzo Von Matterhorn LCA(最近公共祖先)

C. Lorenzo Von Matterhorn time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Barney lives in NYC. NYC has infinite number of intersections numbered with positive integers starting from 1. Ther

Codeforces Round #260 (Div. 1) A. Boredom (DP)

题目链接:http://codeforces.com/problemset/problem/455/A A. Boredom time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Alex doesn't like boredom. That's why whenever he gets bored, he comes up with

Codeforces Round #424 (Div. 2) D. Office Keys(dp)

题目链接:Codeforces Round #424 (Div. 2) D. Office Keys 题意: 在一条轴上有n个人,和m个钥匙,门在s位置. 现在每个人走单位距离需要单位时间. 每个钥匙只能被一个人拿. 求全部的人拿到钥匙并且走到门的最短时间. 题解: 显然没有交叉的情况,因为如果交叉的话可能不是最优解. 然后考虑dp[i][j]表示第i个人拿了第j把钥匙,然后 dp[i][j]=max(val(i,j),min(dp[i-1][i-1~j]))   val(i,j)表示第i个人拿

Codeforces Round #369 (Div. 2) C. Coloring Trees(dp)

题目链接:Codeforces Round #369 (Div. 2) C. Coloring Trees 题意: 有n个树,每个树有一个颜色,如果颜色值为0,表示没有颜色,一共有m个颜色,第j种颜色涂第i棵树需要花费pij,颜色一样且相邻的分为一组 现在要将所有颜色为0的树涂上颜色,使得这些树恰好可以分为k组,问最小的花费 题解: 考虑dp[i][j][k],表示考虑第i棵树涂第j种颜色,当前分为k组的最小花费,然后状态转移看代码,注意的是dp的初始状态 1 #include<bits/std

Codeforces Round #455 (Div. 2) C. Python Indentation dp递推

Codeforces Round #455 (Div. 2) C. Python Indentation 题意:python 里面,给出 n 个 for 循环或陈述语句,'f' 里面必须要有语句.按 python 缩进的方式组合成合法的程序,问有多少种可能方案. tags: dp dp[i][j] 表示第 i 个语句缩进为 j 时的可能方案数, 转移: 1] 如果第 i 个是 'f' , 则第 i+1 个肯定要比第 i 个多缩进一个单位,即 dp[i+1][j] = dp[i][j]. 2]如果

D. Puzzles(Codeforces Round #362 (Div. 2))

D. Puzzles Barney lives in country USC (United States of Charzeh). USC has n cities numbered from 1 through n and n - 1 roads between them. Cities and roads of USC form a rooted tree (Barney's not sure why it is rooted). Root of the tree is the city

Codeforces Round #362 (Div. 2) C. Lorenzo Von Matterhorn (类似LCA)

题目链接:http://codeforces.com/problemset/problem/697/D 给你一个有规则的二叉树,大概有1e18个点. 有两种操作:1操作是将u到v上的路径加上w,2操作是求u到v上的路径和. 我们可以看出任意一个点到1节点的边个数不会超过64(差不多就是log2(1e18)),所以可以找最近相同祖节点的方式写. 用一条边的一个唯一的端点作为边的编号(比如1到2,那2就为这条边的编号),由于数很大,所以用map来存. 进行1操作的时候就是暴力加w至u到LCA(u,v

Codeforces Round #362 (Div. 2) ABCDE

A. Pineapple Incident 题解: 水题...注意没有t+1这种情形 代码: #include<bits/stdc++.h> #define pb push_back #define mp make_pair #define se second #define fs first #define ll long long using namespace std; const int INF=1e9+10; const int maxn=1000000+5; ll read() {