ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【BZOJ3566】[SHOI2014] 概率充电器(树形DP)

2020-01-28 14:53:01  阅读:224  来源: 互联网

标签:概率 标记 ee edge BZOJ3566 SHOI2014 times DP define


点此看题面

大致题意: 有一棵树,其中每条边有一定的概率存在。每个点有一定概率被直接标记,与被标记的点连通的点也会被标记。求被标记的点数的期望。

前言

\(Jan\ 28th\)刷题计划(2/6),算法标签:DP、概率论。

挺简单的一道\(DP\)题吧。

转化

点数的期望其实可以分到每个点上,就相当于每个点的期望之和。

由于一个点的贡献是\(1\),而期望=概率*贡献,所以此处点数的期望就相当于每个点被标记概率之和。

那么,我们只要求出每个点被标记的概率即可。

定义新运算

考虑一个问题:如果一个点有\(x\)的概率通过第一种方式被标记,又有\(y\)的概率通过第二种方式被标记,求这个点被标记的概率。

这个概率应该是\(x+y-xy\)(之所以要减掉\(xy\),是因为如果通过两种方式都标记了它就会计算重复,故减去)。

方便后文描述,我们定义,\(U(x,y)=x+y-xy\)。

再考虑一个问题:如果一个点有\(x\)的概率通过某种方式被标记,而这个点被标记的总概率是\(z\),求这个点以其他方式被标记的概率\(y\)。

因为\(z=U(x,y)=x+y-xy\),所以变形一下就得到了\(y=\frac{z-x}{1-x}\)。

考虑到当\(x=1\)时,\(y\)为任何值都能使原式成立,所以此时我们可以随便给它赋个值,姑且令此时\(y=1\)。

方便后文描述,我们定义,\(T(z,x)=\begin{cases}1&(x=1)\\\frac{z-x}{1-x}&(x≠1)\end{cases}\)。

动态规划

我们设\(f_x\)为\(x\)通过其子树内的点被标记的概率,\(g_x\)为\(x\)通过其子树外的点被标记的概率(这里的子树内和子树外都不包括\(x\)自身)。

容易得到\(f_x\)和\(g_x\)的转移方程分别为:

\[f_x=U_{y∈son_x}(U(p_y,f_y)\times P_{edge})\]

即将通过每个子树被标记的概率统计起来。

\[y∈son_x,g_y=U(U(p_x,g_x),T(f_x,U(p_y,f_y)\times P_{edge}))\times P_{edge}\]

其中\(U(p_x,g_x)\)是\(x\)通过自身及子树外节点被标记的概率,\(T(f_x,U(p_y,f_y)\times P_{edge})\)是\(x\)通过除\(y\)的子树以外其余子树被标记的概率。

应该还是比较好理解的。

最后每个节点被标记的概率就是:

\[U(p_x,U(f_x,g_x))\]

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 500000
#define DB double
#define add(x,y,z) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y,e[ee].p=z/100.0)
#define U(x,y) ((x)+(y)-(x)*(y))
#define T(z,x) ((x)==1?1:((z)-(x))/((1)-(x)))
using namespace std;
int n,ee,lnk[N+5];DB p[N+5],f[N+5],g[N+5];struct edge {int to,nxt;DB p;}e[N<<1];
class FastIO
{
    private:
        #define FS 100000
        #define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
        #define tn (x<<3)+(x<<1)
        #define D isdigit(c=tc())
        char c,*A,*B,FI[FS];
    public:
        I FastIO() {A=B=FI;}
        Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
}F;
I void DP1(CI x,CI lst=0)//第一个树形DP,转移f
{
    for(RI i=lnk[x];i;i=e[i].nxt) e[i].to^lst&&
        (DP1(e[i].to,x),f[x]=U(f[x],U(p[e[i].to],f[e[i].to])*e[i].p));
}
I void DP2(CI x,CI lst=0)//第二个树形DP,转移g
{
    for(RI i=lnk[x];i;i=e[i].nxt) e[i].to^lst&&
        (g[e[i].to]=U(U(p[x],g[x]),T(f[x],U(p[e[i].to],f[e[i].to])*e[i].p))*e[i].p,DP2(e[i].to,x),0);
}
int main()
{
    freopen("a.in","r",stdin);
    RI i,x,y,z;for(F.read(n),i=1;i^n;++i) F.read(x),F.read(y),F.read(z),add(x,y,z),add(y,x,z);
    for(i=1;i<=n;++i) F.read(z),p[i]=z/100.0;DB ans=0;DP1(1),DP2(1);
    for(i=1;i<=n;++i) ans+=U(p[i],U(f[i],g[i]));return printf("%.6lf",ans),0;//统计答案并输出
}

标签:概率,标记,ee,edge,BZOJ3566,SHOI2014,times,DP,define
来源: https://www.cnblogs.com/chenxiaoran666/p/BZOJ3566.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有