=== ===
这里放传送门
=== ===
题解
可以想到用
f[i]
表示从点i逃出去的期望步数。但是这个题因为它有一个概率回到1号点重新开始,所以会存在互相推的问题。通用的解决办法是高斯消元,但这个题的数据范围显然没有办法消。。。
但是题目给的是一棵树,能不能利用这个特点? 设
P[i]
为从点i逃到其它点的概率,就是
P[i]=1−k[i]−e[i]d[i]
。首先列出递推式:
f[i]=∑son(f[son]+1)∗P[i]+(f[fa]+1)∗P[i]+f[1]∗k[i]
如果利用类似树形DP的方法用儿子的结果更新父亲的话,
f[fa]
和
f[1]
就都是未知数,而
f[son]
是已知数,在递推
f[i]
的时候可以当做一个常量。
那么设
f[i]=A[i]∗f[fa]+B[i]∗f[1]+C[i]
。我们希望得到关于
A[i],B[i]
和
C[i]
的递推式。为了递推就需要在式子里面引入
A[son],B[son]
和
C[son]
。利用
f[son]=A[son]∗f[i]+B[son]∗f[1]+C[son]
来代入上面的递推式,得到:
f[i]=∑son(A[son]∗f[i]+B[son]∗f[1]+C[son]+1)∗P[i]+(f[fa]+1)∗P[i]+f[1]∗k[i]
把这个式子展开,把同类项合并,得到
(1−∑sonA[son]∗P[i])∗f[i]=f[fa]∗P[i]+(∑sonB[son]∗P[i]+k[i])∗f[1]+∑son(C[son]+1)∗P[i]+P[i]
那么如果设
T[i]=1−∑sonA[son]∗P[i]
,就有
A[i]=P[i]T[i]
,
B[i]=∑sonB[son]∗P[i]+k[i]T[i]
,
C[i]=(∑sonC[son]∗P[i])+d[i]∗P[i]T[i]
。一遍树形DP就可以求出
A[1]
,
B[1]
和
C[1]
。而因为节点1没有父亲,所以
f[1]=B[1]∗f[1]+C[1]
,也就是
f[1]=C[1]1−B[1]
。计算过程中只要出现被零除的情况就说明无解,输出impossible即可。
代码
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const double eps=
1e-10;
int T,n,p[
10010],a[
20010],tot,nxt[
20010];
double A[
10010],B[
10010],C[
10010],P[
10010],d[
10010],K[
10010],E[
10010];
bool flag;
void add(
int x,
int y){
tot++;a[tot]=y;nxt[tot]=p[x];p[x]=tot;
}
void dfs(
int u,
int fa){
double tmp=
0;
A[u]=P[u];B[u]=K[u];
C[u]=
1-K[u]-E[u];
for (
int i=p[u];i!=
0;i=nxt[i])
if (a[i]!=fa){
dfs(a[i],u);
if (flag==
true)
return;
tmp+=A[a[i]]*P[u];
B[u]+=B[a[i]]*P[u];
C[u]+=C[a[i]]*P[u];
}
tmp=
1.0-tmp;
if (
fabs(tmp)<eps){flag=
true;
return;}
A[u]/=tmp;B[u]/=tmp;C[u]/=tmp;
}
int main()
{
scanf(
"%d",&T);
for (
int wer=
1;wer<=T;wer++){
scanf(
"%d",&n);tot=
0;
memset(d,
0,
sizeof(d));
memset(p,
0,
sizeof(p));
for (
int i=
1;i<n;i++){
int x,y;
scanf(
"%d%d",&x,&y);
add(x,y);add(y,x);
d[x]+=
1;d[y]+=
1;
}
for (
int i=
1;i<=n;i++){
scanf(
"%lf%lf",&K[i],&E[i]);
K[i]/=
100.0;E[i]/=
100.0;
}
for (
int i=
1;i<=n;i++)
P[i]=(
1-K[i]-E[i])/d[i];
flag=
false;dfs(
1,
0);
printf(
"Case %d: ",wer);
if (flag==
true||
fabs(
1.0-B[
1])<eps)
printf(
"impossible\n");
else printf(
"%.6lf\n",C[
1]/(
1-B[
1]));
}
return 0;
}
偏偏在最后出现的补充说明
这类题目是概率与期望题目中经常出现的一个类型。在没有办法使用高斯消元的时候要注意观察题目的性质,有些时候会给出具有明显递推特性的结构。基本思路就是设未知量然后由直接递推答案转为递推未知量的系数。
转载请注明原文地址: https://ju.6miu.com/read-23806.html