zoukankan      html  css  js  c++  java
  • [SHOI2014] 概率充电器

    首先记 (f_u) 表示 (u) 不被以 (u) 为根的子树内点通上电的概率。

    不难列出这样一个式子:

    (f_u=displaystyle(1-p_u)*prod_{v in subtree u}f_v*e(u,v))

    其中 (p_u) 表示直接充 (u) 的概率。

    但是这个式子有个 bug,它处理不了给 (u) 导电的点在 (u) 子树外的情况。

    那么我们采取换根的思想,记 (g_u) 表示 (u) 不通电的概率,则 (g_u) 可以通过 (u) 的子树和剩余部分计算,子树部分我们已经处理过,而剩余部分可以通过 (u) 的父亲计算,记 (h_u) 表示非 (u) 子树里的点导电给 (u) 的概率。

    那么 (h_u = dfrac{g_{fa}}{1-e(fa,u)+e(fa,u)*f_u})

    那么 (g_u = f_u*(1-e(fa,u)+e(fa,u)*f_u))

    那么答案就是 (displaystyle sum_{i=1}^{n}(1-g_i))

    #include <bits/stdc++.h>
    #define reg register
    #define ll long long
    using namespace std;
    const int MAXN = 5e5 + 10;
    int n, E, head[MAXN], nxt[MAXN << 1], pnt[MAXN << 1];
    double val[MAXN << 1], p[MAXN], f[MAXN], g[MAXN], h[MAXN];
    inline void clear() {
      E = 0, memset(head, -1, sizeof(head));
    }
    inline void addedge(int x, int y, double v) {
      nxt[E] = head[x], pnt[E] = y, val[E] = v, head[x] = E++;
    }
    inline void dfs1(int u, int fa) {
      f[u] = 1 - p[u];
      for(reg int i = head[u]; i != -1; i = nxt[i]) {
        int v = pnt[i];
        if(v == fa) continue;
        dfs1(v, u), f[u] *= (1 - val[i] + val[i] * f[v]);
      }
    }
    inline void dfs2(int u, int fa, int id) {
      if(u == 1) g[u] = f[u];
      else h[u] = g[fa] / (1 - val[id] + val[id] * f[u]), g[u] = f[u] * (1 - val[id] + val[id] * h[u]);
      for(reg int i = head[u]; i != -1; i = nxt[i]) {
        int v = pnt[i];
        if(v == fa) continue;
        dfs2(v, u, i);
      }
    }
    inline void work() {
      scanf("%d", &n), clear();
      for(reg int i = 1; i < n; ++i) {
        int u, v;
        double d;
        scanf("%d%d%lf", &u, &v, &d), d *= 0.01, addedge(u, v, d), addedge(v, u, d);
      }
      for(reg int i = 1; i <= n; ++i) scanf("%lf", &p[i]), p[i] *= 0.01;
      dfs1(1, 0), dfs2(1, 0, 0);
      double ans = 0;
      for(reg int i = 1; i <= n; ++i) ans += 1.0 - g[i];
      printf("%.6f
    ", ans);
    }
    int main() {
      int _ = 1;
      // scanf("%d", &_);
      while(_--) work();
      return 0;
    }
    
    
  • 相关阅读:
    C++中析构函数为什么要是虚函数
    依赖注入(IOC)
    ParseInt()与NaN()
    仿windows关机效果
    类似Tab的效果
    飞来飞去的广告
    Sql Server 三种连接
    JS日期处理
    绚丽的注册效果
    JS图片自动切换
  • 原文地址:https://www.cnblogs.com/Lonely-233/p/13659045.html
Copyright © 2011-2022 走看看