LGP4284题解

这个题,题面是【】,出题人也是个【】

真就只放前向星过,把 vector 和离线建图都卡了。。。

题意:

一棵树,一条边有 \(p_i\) 的概率连接两个节点,一个点有 \(P_i\) 的概率亮着,问所有节点亮着的期望。

首先根据期望的线性性,所有节点亮着的期望明显可以拆成每个节点亮着的期望之和。然后仔细想想,\(E(X)=1 * p +0 * (1-p)=p\),所以只需要求亮着的概率即可。

怎么算呢?

考虑 dp,设 \(dp_1[u]\)\(u\) 为根的子树中,\(u\) 亮着的概率。

直接算很困难,考虑算 \(u\) 不亮着的概率,不难发现是 \((1-P_u)\prod_{\texttt {v is u son}}(1-dp1[v] \times p_{(u,v)})\),用 \(1\) 减去即可得到 \(dp_1[u]\)

接下来考虑换根。要求的东西还是一样的,只是需要维护父节点的 \(dp\) 值。

\(dp_2[u]\) 为考虑整棵树时 \(u\) 亮着的概率,此处为了方便设 \(f[u]\) 为去掉 \(u\) 为根的子树时,其父亲节点亮着的概率。

对于 \(u\) 的一个儿子 \(v\),我们很容易能够发现有 \(f[v]=(1-p_{(u,f[v])}\prod_{\texttt {x is u son }\And x \ne v } 1-dp1[x] \times e_{(u,x)})\)

大多数同学都是直接用 \(dp2[u]\)\(dp1[v]\) 直接进行转移,来得到其值,但其实可以对儿子维护一个前缀积和后缀积,这样就不会出现除法的问题了。

#include<cstdio>
#include<vector>
#include<cctype>
typedef double db;
const int M=5e5+5;
int n,m,cnt,h[M],f[M];db ans,p[M],dp1[M],dp2[M];
db v[M],lp[M],rp[M];
struct Edge{
	int v,nx;db p;
}e[M<<1];
inline void Add(const int&u,const int&v,const db&p){
	e[++cnt]=(Edge){v,h[u],p};h[u]=cnt;
	e[++cnt]=(Edge){u,h[v],p};h[v]=cnt;
}
inline int read(){
	int n(0);char s;
	while(!isdigit(s=getchar()));
	while(n=n*10+(s&15),isdigit(s=getchar()));
	return n;
}
void DFS1(int u){
	dp1[u]=1-p[u];
	for(int E=h[u];E;E=e[E].nx)if(e[E].v^f[u])f[e[E].v]=u,DFS1(e[E].v),dp1[u]*=(1-dp1[e[E].v]*e[E].p);dp1[u]=1-dp1[u];
}
void DFS2(int u){
	int e,i,len(0);db p=(dp2[u]*=1-::p[u]);
	for(e=h[u];e;e=::e[e].nx)if(::e[e].v^f[u])v[++len]=1-dp1[::e[e].v]*::e[e].p;
	for(i=1;i<=len;++i)lp[i]=(i==1?1:lp[i-1])*v[i];
	for(i=len;i>=1;--i)rp[i]=(i==len?1:rp[i+1])*v[i];
	for(e=h[u],i=1;e;e=::e[e].nx){
		if(::e[e].v==f[u])continue;Edge&E=::e[e];dp2[E.v]*=p;dp2[u]*=1-dp1[E.v]*E.p;
		if(i^1)dp2[E.v]*=lp[i-1];if(i^len)dp2[E.v]*=rp[i+1];
		dp2[E.v]=1-(1-dp2[E.v])*E.p;++i;
	}
	for(e=h[u];e;e=::e[e].nx)if(::e[e].v^f[u])DFS2(::e[e].v);dp2[u]=1-dp2[u];
}
signed main(){
	int i,u,v,p;n=read();
	for(i=1;i<n;++i)u=read(),v=read(),p=read(),Add(u,v,.01*p);
	for(i=1;i<=n;++i)::p[i]=.01*read(),dp2[i]=1;DFS1(1);DFS2(1);
	for(i=1;i<=n;++i)ans+=dp2[i];printf("%.6f",ans);
}
posted @ 2022-01-11 14:37  Prean  阅读(5)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};