Codeforces 696B Puzzles(期望+树形dp)

来源:互联网 发布:dnspod和阿里云解析 编辑:程序博客网 时间:2024/06/05 00:44

题意:

对树做dfs的时候,每一个点都有一个时间戳,问你如果每次选择子节点都是等概率的情况下,每个点的期望时间戳是多少。

解法:

一看就是典型的树形dp求期望的题目,我们考虑的是其他的点对某一个点的贡献度,最后的出的转移方程就是dp[v] = dp[u] + 1 + (sz[u] - sz[v] - 1]) * 0.5。
得到这个方程有两个方法,第一种很好理解,首先子节点最起码比父节点要大1,然后考虑这个子节点和其他兄弟节点的关系,其他的兄弟节点要么在他之前访问,要么在这时候访问,概率都是0.5,所以对这个店的贡献就是其他兄弟节点的子树大小乘以0.5;第二种,我们就需要推导一下公式,我就不具体写出来了,大概的思路就是假设当前节点是在所有兄弟节点中第i个被访问的,那么他的期望就是前面i-1个节点的期望再乘以概率计科,虽然对于某一次的期望的式子比较复杂,但是把他们都求和之后,就会发现能够消掉很多东西,最后也就得到了上面的式子。
代码力两次dfs就可以搞定,很简单。

//  Created by  CQU_CST_WuErli//  Copyright (c) 2016 CQU_CST_WuErli. All rights reserved.////#pragma comment(linker, "/STACK:102400000,102400000")#include <iostream>#include <cstring>#include <cstdio>#include <cstdlib>#include <cctype>#include <cmath>#include <string>#include <vector>#include <map>#include <queue>#include <stack>#include <set>#include <algorithm>#include <sstream>#define CLR(x) memset(x,0,sizeof(x))#define OFF(x) memset(x,-1,sizeof(x))#define MEM(x,a) memset((x),(a),sizeof(x))#define BUG cout << "I am here" << endl#define lookln(x) cout << #x << "=" << x << endl#define SI(a) scanf("%d", &a)#define SII(a,b) scanf("%d%d", &a, &b)#define SIII(a,b,c) scanf("%d%d%d", &a, &b, &c)const int INF_INT=0x3f3f3f3f;const long long INF_LL=0x7f7f7f7f;const int MOD=1e9+7;const double eps=1e-10;const double pi=acos(-1);typedef long long  ll;using namespace std;int n;vector<int> g[100010];int sz[100010];double ans[100010];void dfs1(int u) {    sz[u] = 1;    for (auto& v : g[u]) {        dfs1(v);        sz[u] += sz[v];    }}void dfs2(int u) {    for (auto& v : g[u]) {        ans[v] = ans[u] + 1 + (double)(sz[u] - sz[v] - 1) / 2.0;        dfs2(v);    }}int main(int argc, char const *argv[]) {#ifdef LOCAL    freopen("C:\\Users\\john\\Desktop\\in.txt","r",stdin);    // freopen("C:\\Users\\john\\Desktop\\out.txt","w",stdout);#endif    while (SI(n) == 1) {        for (int i = 1; i <= n; i++)            g[i].clear(), sz[i] = 0, ans[i] = 0;        for (int i = 2; i <= n; i++) {            int x; SI(x);            g[x].push_back(i);        }        dfs1(1);        ans[1] = 1;        dfs2(1);        for (int i = 1; i <= n; i++)            printf("%f\n", ans[i]);    }    return 0;
0 0
原创粉丝点击