題目鏈接
題意
有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;
}