Description
题目简述:
你被困在一个迷宫里面,这个迷宫是一颗树,每一个结点都有一个出口,且第(i)结点都有三种可能:
- 有(k_i)的概率被杀死,杀死后你会回到1号结点
- 有(e_i)的概率逃脱
- 有(1-k_i-e_i)的概率从与(i)相邻的(m)条边出去(所以走与(i)相邻一条边的概率是(frac {1-k_i-e_i}{m}))
求逃出迷宫的期望步数。
Solution
假设(dp_i)表示从第(i)个结点出发逃脱的期望步数,(f_i)为(i)号结点的父亲结点,(son_i)为(i)号结点的儿子结点,那么有:
发现可以把它们设置成统一形式:(dp_i=A_i*dp_1+B_i*dp_{f_i}+C_i)。
对于非叶子结点(i),设它的儿子为(j):
(sum dp_{son_i}=sum (A_j*dp_1+B_j*dp_i+C_j)\dp_i=A_i*dp_1+B_i*dp_{f_i}+frac {1-k_i-e_i}{m}*sum(A_{son_i}*dp_1+B_{son_i}*dp_i+C_{son_i})+1-k_i-e_i\=(A_i+(sum A_{son_i})*frac {1-k_i-e_i}{m})*dp_1+B_i*dp_{f_i}+frac {1-k_i-e_i}{m}*(sum B_{son_i})*dp_i+frac {1-k_i-e_i}{m}*sum C_{son_i}+1-k_i-e_i\ herefore (1-frac {1-k_i-e_i}{m}*sum B{son_i})*dp_i=(k_i+(sum A_{son_i})*frac {1-k_i-e_i}{m})*dp_1+frac {1-k_i-e_i}{m}*dp_{f_i}+frac {1-k_i-e_i}{m}*sum C_{son_i}+1-k_i-e_i\)
这样下来,(dp_i)的(A_i,B_i,C_i)都只与儿子结点有关了,就可以从下往上计算,最终答案就是(dp_1)。
注意:如果有一个结点的逃脱期望步数是0,那么无解,因为有可能一直在循环。
Code
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cmath>
#define sz(x) (int)x.size()
using namespace std;
const int N=1e4+5;
int T,n,du[N];
double p[N][3],A[N],B[N],C[N];
vector<int> e[N];
inline int read () {
int res=0,fl=1;
char ch;
while ((ch=getchar())&&(ch<'0'||ch>'9')) if (ch=='-') fl=-1;
res=ch^48;
while ((ch=getchar())&&ch>='0'&&ch<='9') res=(res<<1)+(res<<3)+(ch^48);
return res*fl;
}
inline bool dfs (int x,int fa) {//cout<<x<<endl;
int son=du[x];
A[x]=p[x][0];
B[x]=p[x][2]/son;
C[x]=p[x][2];
double tmp=0;
for (int i=0;i<sz(e[x]);i++) {
int v=e[x][i];
if (v==fa) continue;
if (!dfs(v,x)) return false;
A[x]+=p[x][2]/son*A[v];
C[x]+=p[x][2]/son*C[v];
tmp+=p[x][2]/son*B[v];
}
if (fabs(1-tmp)<1e-9) return false;
A[x]/=1-tmp;
B[x]/=1-tmp;
C[x]/=1-tmp;
return true;
}
inline void clean () {
memset(A,0,sizeof(A));
memset(B,0,sizeof(B));
memset(C,0,sizeof(C));
memset(du,0,sizeof(du));
for (int i=1;i<=n;i++) e[i].clear();
}
int main () {
// freopen("4035.in","r",stdin);
// freopen("4035.out","w",stdout);
T=read();
for (int t=1;t<=T;t++) {
n=read();
clean();
for (int i=1;i<n;i++) {
int u=read(),v=read();du[u]++;du[v]++;
e[u].push_back(v);e[v].push_back(u);
}
for (int i=1;i<=n;i++) p[i][0]=read()/100.0,p[i][1]=read()/100.0;
for (int i=1;i<=n;i++) p[i][2]=1-p[i][0]-p[i][1];
// cout<<p[1][0]<<endl;
printf("Case %d: ",t);
if (dfs(1,1)&&fabs(1-A[1])>1e-9) printf("%.6lf
",C[1]/(1-A[1]));
else puts("impossible");
}
return 0;
}