设f[i]表示从点i逃出去的期望步数,显然有递推式$f[i]=Ki\cdot f[1]+(1-Ei-Ki)/s[i](f[fa]+1+\sum_{son}(f[son]+1))$(其中r[i]表示点i的度)。
这个用高斯消元复杂度高达三次,无法通过,但可以发现每一个点一定可以用$f[i]=a*f[1]+b*f[fa]+c$来表示,从叶子节点不断推上去就可以算出点1具体的a、b和c,然后就可以解出f[1](即答案)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 10005 4 struct ji{ 5 int nex,to; 6 }edge[N<<1]; 7 int E,t,n,x,y,p1[N],p2[N],head[N]; 8 double a[N],b[N],c[N]; 9 void add(int x,int y){ 10 edge[E].nex=head[x]; 11 edge[E].to=y; 12 head[x]=E++; 13 } 14 void dfs(int k,int fa){ 15 double s=(fa>0),t=a[k]=c[k]=0; 16 for(int i=head[k];i!=-1;i=edge[i].nex) 17 if (edge[i].to!=fa){ 18 int v=edge[i].to; 19 dfs(v,k); 20 s++; 21 a[k]+=a[v]; 22 t+=b[v]; 23 c[k]+=c[v]+1; 24 } 25 s=0.01*(100-p1[k]-p2[k])/s; 26 t=1-t*s; 27 a[k]=(a[k]*s+0.01*p1[k])/t; 28 b[k]=s/t; 29 c[k]=(c[k]+(fa>0))*s/t; 30 } 31 int main(){ 32 scanf("%d",&t); 33 for(int ii=1;ii<=t;ii++){ 34 scanf("%d",&n); 35 E=0; 36 memset(head,-1,sizeof(head)); 37 for(int i=1;i<n;i++){ 38 scanf("%d%d",&x,&y); 39 add(x,y); 40 add(y,x); 41 } 42 for(int i=1;i<=n;i++)scanf("%d%d",&p1[i],&p2[i]); 43 dfs(1,0); 44 if (a[1]==1)printf("Case %d: impossible\n",ii); 45 else printf("Case %d: %.6f\n",ii,c[1]/(1.0-a[1])); 46 } 47 }