HDU 4035 Maze(树形概率DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4035

题意:一棵树,从结点1出发,在每个结点 i 都有3种可能:(1)回到结点1 , 概率 Ki;(2)结束,概率 Ei;(3)随机走一条边。(ki+ei+随机走=1) 求到结束需要走的边数的期望。

假设E[i]为点i到结束走边数的期望,则有

(以下m为点的度数)

E[i]=ki*E[1]+(1-ei-ki)/m*(E[fa[i]]+1)若i为叶子节点.

=ki*E(1)+(1-ki-ei)*E(father)+(1-ki-ei) 

E[i]=ki*E[1]+(1-ei-ki)/m*(E[fa[i]]+1)+(1-ei-ki)/m*(Sum(E[son[i]]+1))i不为叶子节点

=ki*E(1)+(1-ki-ei)/m *E(father)+(1-ki-ei)/m*SUM(E(child))+(1-ki-ei)  作为1式

我们发现,这样求非常麻烦,若是n小一点大可用高斯消元求解,可这题的n为10000,无法用高斯消元。

对于每个E[i],我们令E[i]=Ai*(E[1])+Bi*(E[fa[i]])+Ci

E[child]=Aj*E[1]+Bj*E[i]+Cj

Sum(E[child])=Sum(Aj*E[1]+Bj*E[i]+Cj)

带入1式:ki*E(1)+(1-ki-ei)/m *E(father)+(1-ki-ei)/m*Sum(Aj*E[1]+Bj*E[i]+Cj)+(1-ki-ei)

可得:(ki+(1-ki-ei)/m*SUM(Aj))*E(1)+(1-ki-ei)/m *E(father)+(1-ki-ei+(1-ki-ei)/m*SUM(cj))

与刚才的E[i]=Ai*(E[1])+Bi*(E[fa[i]])+Ci对比一下发现:

Ai=(ki+(1-ki-ei)/m*SUM(Aj))

Bi=(1-ki-ei)/m 

Ci=(1-ki-ei+(1-ki-ei)/m*SUM(cj))

对于叶子节点,有

Ai=ki

Bi=1-ki-ei

Ci=1-ki-ei

倒推即可,还有,

E(1)=A1*E(1)+B1*0+C1

E(1)=C1/(1-A1)

若是上述式子中的分母出现0则无解。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<cmath>
 5 #include<algorithm>
 6 const double eps=1e-9;
 7 int tot,go[500005],first[500005],next[500005];
 8 double a[500005],b[500005],c[500005],k[500005],e[500005];
 9 int n,du[500005];
10 void insert(int x,int y){tot++;go[tot]=y;next[tot]=first[x];first[x]=tot;}
11 void add(int x,int y){insert(x,y);insert(y,x);}
12 bool dfs(int x,int fa){
13     bool Isleave=1;
14     double tmp=0;
15     a[x]=k[x];
16     b[x]=c[x]=(1-k[x]-e[x]);
17     b[x]/=du[x];
18     for (int i=first[x];i;i=next[i]){
19         int pur=go[i];
20         if (pur==fa) continue;
21         Isleave=0;
22         if (!dfs(pur,x)) return false;
23         a[x]+=a[pur]*(1-k[x]-e[x])/du[x];
24         c[x]+=c[pur]*(1-k[x]-e[x])/du[x];
25         tmp+=(b[pur])*(1-k[x]-e[x])/du[x];
26     }
27     if (fabs(tmp-1)<=eps) return false;
28     a[x]/=(1-tmp);
29     b[x]/=(1-tmp);
30     c[x]/=(1-tmp);
31     return true;
32 }
33 int main(){
34     int T,Tcase=0;
35     scanf("%d",&T);
36     while (T--){
37         Tcase++;
38         tot=0;
39         memset(first,0,sizeof first);
40         memset(du,0,sizeof du);
41         scanf("%d",&n);
42         for (int i=1;i<n;i++){
43             int x,y;
44             scanf("%d%d",&x,&y);
45             add(x,y);
46             du[x]++;
47             du[y]++;
48         }
49         for (int i=1;i<=n;i++){
50             scanf("%lf%lf",&k[i],&e[i]);
51             k[i]/=100;e[i]/=100;
52         }
53         printf("Case %d: ",Tcase);
54         if (dfs(1,0)&&fabs(1-a[1])>eps){
55             printf("%.6f
",c[1]/(1-a[1]));
56         }
57         else{
58             printf("impossible
");
59         }
60     }
61 }
原文地址:https://www.cnblogs.com/qzqzgfy/p/5543901.html