Codeforces123E. Maze树形dp概率dp证明题

Posted dream-maker-yk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces123E. Maze树形dp概率dp证明题相关的知识,希望对你有一定的参考价值。

LINK


题目大意

一棵树,上面的每个点都有一定概率成为起点和终点

从起点出发,随机游走,并按照下列规则统计count:

DFS(x)
    if x == exit vertex then
        finish search
    flag[x] <- TRUE
    random shuffle the vertices' order in V(x) // here all permutations have equal probability to be chosen
    for i <- 1 to length[V] do
        if flag[V[i]] = FALSE then
            count++;
            DFS(y);
    count++;

求count的期望


思路

首先来证明一个东西:

对于每个节点u,如果这个节点是终点,那么他的贡献是
[ sum_{(u,v)in E}siz_v*sump_v ]
(sump_v)是子树内每个节点作为起始节点的概率和

首先我们把一个以u为根子树拿出来,对于其中的每一个点v

如果起始节点s在v的子树内,v一定会被经过1次,贡献(p_s)

如果s不在v的子树内,v有(frac{1}{2})的概率会被经过,贡献(p_s*2*frac{1}{2}=p_s)

不被经过的贡献是(0)

然后来证为为什么有(frac{1}{2})的概率被经过

从s开始进入每个子树,要么遍历完,要么停下来

所以可以认为任何一个子树在停下来之前被访问的概率都是(frac{1}{2})

然后这题做完了。。。泪奔ing


#include<bits/stdc++.h>

using namespace std;

typedef double db;

const int N = 1e5 + 10;

int n, siz[N];
vector<int> g[N]; 
db p[N], q[N], sump = 0, sumq = 0, ans;

void dfs(int u, int fa) {
  siz[u] = 1;
  for (auto v : g[u]) {
    if (v == fa) continue;
    dfs(v, u);
    siz[u] += siz[v];
    p[u] += p[v];
    ans += q[u] * siz[v] * p[v];
  }
  ans += q[u] * (n - siz[u]) * (sump - p[u]);
}

int main() {
  scanf("%d", &n);
  for (int i = 1; i < n; i++) {
    int u, v;
    scanf("%d %d", &u, &v);
    g[u].push_back(v);
    g[v].push_back(u); 
  }
  for (int i = 1; i <= n; i++) {
    scanf("%lf %lf", &p[i], &q[i]);
    sump += p[i], sumq += q[i];
  }
  dfs(1, 0);
  printf("%.15lf", ans / (sump * sumq));
  return 0;
} 

以上是关于Codeforces123E. Maze树形dp概率dp证明题的主要内容,如果未能解决你的问题,请参考以下文章

HDU 4035 Maze(树形概率DP)

CodeForces - 123E Maze

[经典好题]HDU4035 Maze 期望树形DP

HDU4035 Maze 树形DP期望DP

Codeforces 765E. Tree Folding [dfs][树形dp]

bzoj 4424: Cf19E Fairy && codeforces 19E. Fairy树形dp