【BZOJ3566】【SHOI2014】概率充电器(树形期望DP)

2019-04-14 19:31发布

Description

click me

Solution

参考博客
直接求每个点充电的概率显然不太方便(其实还是很方便的,只是我太菜了。。),所以我们考虑求每个点不能充电的概率,这包括三个方面:
1. 节点的儿子没有传电(儿子没有电或者边不连通)
2. 自己没有电
3. 父亲没有传电(父亲没有电或者边不连通)
我们用fu" role="presentation" style="position: relative;">fu表示该节点没有点且儿子没有传电的概率,那么有:fu=(1qu)vchildren(u)fv+(1pu,v)(1fv)" role="presentation">fu=(1qu)vchildren(u)fv+(1pu,v)(1fv)
gu" role="presentation" style="position: relative;">gu表示该节点没有从父亲传电的概率,设P" role="presentation" style="position: relative;">P为父亲没有点的概率,且v" role="presentation" style="position: relative;">vu" role="presentation" style="position: relative;">u的父亲,由于我们已经认为u" role="presentation" style="position: relative;">u没有电了,所以要除去u" role="presentation" style="position: relative;">u对于fv" role="presentation" style="position: relative;">fv的贡献,即:P=gvfvfu+(1pu,v)(1fu)" role="presentation">P=gvfvfu+(1pu,v)(1fu)
得到:gu=P+(1P)(1pu,v)" role="presentation">gu=P+(1P)(1pu,v)
所以答案是:Ans=i=1n1figi" role="presentation">Ans=i=1n1figi

Source

/**************************** * Au: Hany01 * Prob: BZOJ3566 & SHOI2014 概率充电器 * Date: Feb 7th, 2018 * Email: hany01@foxmail.com ****************************/ #include using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef vector<int> VI; #define rep(i , j) for (int i = 0 , i##_end_ = j; i < i##_end_ ; ++ i) #define For(i , j , k) for (int i = (j) , i##_end_ = (k) ; i <= i##_end_ ; ++ i) #define Fordown(i , j , k) for (int i = (j) , i##_end_ = (k) ; i >= i##_end_ ; -- i) #define Set(a , b) memset(a , b , sizeof(a)) #define SZ(a) ((int)(a.size())) #define ALL(a) a.begin(), a.end() #define pb(a) push_back(a) #define mp(a, b) make_pair(a, b) #define INF (0x3f3f3f3f) #define INF1 (2139062143) #define Mod (1000000007) #define y1 wozenmezhemecaia #ifdef hany01 #define debug(...) fprintf(stderr , __VA_ARGS__) #else #define debug(...) #endif inline void File() { #ifdef hany01 freopen("bzoj3566.in" , "r" , stdin); freopen("bzoj3566.out" , "w" , stdout); #endif } template<typename T> inline bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; } template<typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; } inline int read() { register char c_; register int _ , __; for (_ = 0 , __ = 1 , c_ = getchar() ; !isdigit(c_) ; c_ = getchar()) if (c_ == '-') __ = -1; for ( ; isdigit(c_) ; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48); return _ * __; } const int maxn = 500005, maxm = 1000005; int n, beg[maxn], v[maxm], nex[maxm], e; double p[maxm], f[maxn], g[maxn], Ans, q[maxn]; inline void add(int uu, int vv, int pp) { v[++ e] = vv, p[e] = pp / 100.0, nex[e] = beg[uu], beg[uu] = e; } inline void Init() { register int uu, vv, pp; n = read(); For(i, 2, n) uu = read(), vv = read(), pp = read(), add(uu, vv, pp), add(vv, uu, pp); For(i, 1, n) q[i] = read() / 100.0; } inline void dfs1(int u, int fa) { f[u] = 1 - q[u]; for (register int i = beg[u]; i; i = nex[i]) if (v[i] != fa) dfs1(v[i], u), f[u] *= (f[v[i]] + (1 - p[i]) * (1 - f[v[i]])); } inline void dfs2(int u, int fa) { register double P; for (register int i = beg[u]; i; i = nex[i]) if (v[i] != fa) P = g[u] * f[u] / (f[v[i]] + (1 - f[v[i]]) * (1 - p[i])), g[v[i]] = P + (1 - P) * (1 - p[i]), dfs2(v[i], u); } int main() { File(); Init(); dfs1(1, 0); g[1] = 1, dfs2(1, 0); For(i, 1, n) Ans += 1 - f[i] * g[i]; printf("%.6lf ", Ans); return 0; } //高楼目尽欲黄昏,梧桐叶上萧萧雨。 // -- 晏殊《踏莎行·碧海无波》