题目链接: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 }