题目链接
题意
有n个房间,由n-1条通道连通起来,实际上就形成了一棵树,从结点1出发,开始走,在每个结点i都有3种可能:
1.被杀死,回到结点1处(概率为ki)
2.找到出口,走出迷宫 (概率为ei)
3.和该点相连有m条边,随机走一条
求:走出迷宫所要走的步数的期望值。
题解
设:i号点走出迷宫步数的期望为
容易写出:
对于叶子节点i:
对于非叶子节点i:
我们发现,对于每个点,他的期望都与他父亲的期望和1号点的期望有关。我们可以写出这种形式:
对于非叶子节点
将它代入上式:
化简后有:
即:
现在
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
struct edge{
int x,next;
}ed[20010];
int first[10010],du[10010],tot,n,m,x,y,T,id;
double a[10010],b[10010],c[10010],e[10010],k[10010];
void add(int x,int y){
ed[++tot].x=y;
ed[tot].next=first[x];
first[x]=tot;
}
bool dfs(int x,int y){
int m=du[x];
a[x]=k[x];
b[x]=(1-k[x]-e[x])/m;
c[x]=1-k[x]-e[x];
double tmp=0;
for(int i=first[x];i;i=ed[i].next)
if(ed[i].x!=y){
if(!dfs(ed[i].x,x)) return false;
a[x]+=(1-k[x]-e[x])/m*a[ed[i].x];
c[x]+=(1-k[x]-e[x])/m*c[ed[i].x];
tmp+=(1-k[x]-e[x])/m*b[ed[i].x];
}
if(fabs(tmp-1)<1e-9) return false;
a[x]/=1-tmp;
b[x]/=1-tmp;
c[x]/=1-tmp;
return true;
}
int main(){
for(scanf("%d",&T);T;T--,id++){
memset(first,0,sizeof(first));
memset(du,0,sizeof(du));
scanf("%d",&n); tot=0;
for(int i=1;i<n;i++){
scanf("%d%d",&x,&y);
add(x,y); add(y,x);
du[x]++; du[y]++;
}
for(int i=1;i<=n;i++){
scanf("%lf%lf",&k[i],&e[i]);
k[i]/=100.0; e[i]/=100.0;
}
printf("Case %d: ",id+1);
if(dfs(1,0)&&fabs(1-a[1])>1e-9) printf("%.6f\n",c[1]/(1-a[1]));
else puts("impossible");
}
return 0;
}