码迷,mamicode.com
首页 > 其他好文 > 详细

【题解】SHOI2014概率充电器

时间:2018-07-20 22:28:18      阅读:167      评论:0      收藏:0      [点我收藏+]

标签:++   ble   main   std   转化   获取   充电器   center   cnp   

  首先发现答案就是每个节点有电的概率之和。有电的概率牵扯太广不好求,所以转化为求没有电的概率。这题最难的部分在于:一个节点如果有电,可以来自儿子,也可以来自父亲。我们考虑将这两个部分分离开来:建立状态 \(g[i]\) 和 \(f[i]\) 分别表示一个节点不由子树节点供电的概率以及不由父亲节点供电的概率。

\(g[u] = \prod (g[v] + (1 - g[v]) * (1 - w(u, v))])\)

其中\(v\) 为 \(u\) 的子节点,\(w(u, v)\) 为 \(u, v\) 边有电的概率

  利用这个递推式我们可以dfs一遍自下而上获取所有节点的 \(g[u]\);

  然后考虑如何求得 \(f[u]\)。要注意由于 \(f[u]\) 是 \(u\) 的父亲不供电给 \(u\) 的概率,所以在利用父亲的信息时应该要除去儿子的影响:

父亲 \(F\) 没有电的概率 \(P = (1 - p[F]) * f[F] * \frac{g[F]}{g[u] + (1 - g[u]) * w(F, u))} \)

父亲不供电给儿子的概率为 :

\(f[u] = P + (1 - P) * (1 - w(F, u))\)

  这样就解决啦~

#include <bits/stdc++.h>
using namespace std;
#define maxn 505000
#define db double
#define eps 0.0000001

int n, cnp = 1;
int head[maxn];
db ans, p[maxn], f[maxn], g[maxn];

struct edge
{
    int to, last; db co;
}E[maxn * 2];

void add(int u, int v, db w)
{
    E[cnp].to = v, E[cnp].co = w;
    E[cnp].last = head[u], head[u] = cnp ++;
}

bool check(db x) { return abs(x - 0.0) < eps; }

void dfs(int u, int fa)
{
    f[u] = 1.0;
    for(int i = head[u]; i; i = E[i].last)
    {
        int v = E[i].to;
        if(v == fa) continue;
        dfs(v, u);
        f[u] *= f[v] + (1.0 - f[v]) * (1.0 - E[i].co);
    } 
    f[u] *= (1.0 - p[u]);
} 

void dfs2(int u, int fa)
{
    for(int i = head[u]; i; i = E[i].last)
    {
        int v = E[i].to;
        if(v == fa) continue;
        db P = g[u] * f[u] / (f[v] + (1.0 - f[v]) * (1.0 - E[i].co));
        g[v] = P + (1.0 - P) * (1.0 - E[i].co);
        dfs2(v, u);
    }
    ans += 1.0 - (g[u] * f[u]);
}

int main()
{
    scanf("%d", &n);
    for(int i = 1; i < n; i ++)
    {
        int a, b, p;
        scanf("%d%d%d", &a, &b, &p);
        add(a, b, (db) p / 100.0);
        add(b, a, (db) p / 100.0);
    }
    for(int i = 1; i <= n; i ++) scanf("%lf", &p[i]), p[i] /= 100.0;
    g[1] = 1.0;
    dfs(1, 0); dfs2(1, 0);
    printf("%.6lf\n", ans);
    return 0;
}

 

 

【题解】SHOI2014概率充电器

标签:++   ble   main   std   转化   获取   充电器   center   cnp   

原文地址:https://www.cnblogs.com/twilight-sx/p/9343716.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!