Maze
状态表示:
f
u
f_u
fu表示在
u
u
u节点走出迷宫期望次数,
d
u
d_u
du表示度数
首先很容易想到下面式子
f
u
=
k
u
×
f
1
+
(
1
−
k
u
−
e
u
)
×
∑
u
→
v
f
v
+
1
d
u
f_u=k_u×f_1+(1-k_u-e_u)×\frac{\sum _{u\to v}f_v+1}{d_u}
fu=ku×f1+(1−ku−eu)×du∑u→vfv+1
每个节点有一个类似的式子,也就是
n
n
n个式子,
n
n
n个未知量我们需要求出
f
1
f_1
f1显然可以高斯消元
O
(
n
3
)
O(n^3)
O(n3)但是看了
1
≤
n
≤
1
0
4
1\leq n\leq 10^4
1≤n≤104留下了可惜的泪水~~
之前也做过返回起点的题目,只需要在dp时候多记录一维信息于是向初中解方程那样求解即可这样时间复杂度就能优化到
O
(
n
)
O(n)
O(n),不过本题在树上,好像也不可行其实可以
对于“返回”在树上是如何体现的?
不难想到返回祖先,而此题中就是返回父亲以及返回根节点
1
1
1,于是效仿返回题目的做法,列出下面方程
f
u
=
k
u
×
f
1
+
1
−
k
u
−
e
u
d
u
×
(
f
f
a
+
1
)
+
1
−
k
u
−
e
u
d
u
×
∑
v
∈
s
o
n
u
(
f
v
+
1
)
f_u=k_u×f_1+\frac{1-k_u-e_u}{d_u}×(f_{fa}+1)+\frac{1-k_u-e_u}{d_u}×\sum_{v\in son_u}{(f_v+1)}
fu=ku×f1+du1−ku−eu×(ffa+1)+du1−ku−eu×v∈sonu∑(fv+1)
稍微化简一下
f
u
=
k
u
×
f
1
+
1
−
k
u
−
e
u
d
u
×
f
f
a
+
1
−
k
u
−
e
u
d
u
×
∑
v
∈
s
o
n
u
f
v
+
(
1
−
k
u
−
e
u
)
f_u=k_u×f_1+\frac{1-k_u-e_u}{d_u}×f_{fa}+\frac{1-k_u-e_u}{d_u}×\sum_{v\in son_u}{f_v}+(1-k_u-e_u)
fu=ku×f1+du1−ku−eu×ffa+du1−ku−eu×v∈sonu∑fv+(1−ku−eu)
我们发现所有dp式子都可以写成
f
u
=
a
u
×
f
1
+
b
u
×
f
f
a
+
c
u
f_u=a_u×f_1+b_u×f_{fa}+c_u
fu=au×f1+bu×ffa+cu
由于
f
a
v
=
u
fa_v=u
fav=u上述式子还能化简得
f
v
=
a
v
×
f
1
+
b
v
×
f
u
+
c
v
f_v=a_v×f_1+b_v×f_u+c_v
fv=av×f1+bv×fu+cv
f
u
=
k
u
×
f
1
+
1
−
k
u
−
e
u
d
u
×
f
f
a
+
1
−
k
u
−
e
u
d
u
×
∑
v
∈
s
o
n
u
(
a
v
×
f
1
+
b
v
×
f
u
+
c
v
)
+
(
1
−
k
u
−
e
u
)
f_u=k_u×f_1+\frac{1-k_u-e_u}{d_u}×f_{fa}+\frac{1-k_u-e_u}{d_u}×\sum_{v\in son_u}{(a_v×f_1+b_v×f_u+c_v)}+(1-k_u-e_u)
fu=ku×f1+du1−ku−eu×ffa+du1−ku−eu×v∈sonu∑(av×f1+bv×fu+cv)+(1−ku−eu)
于是有更平凡的式子
(
1
−
1
−
k
u
−
e
u
d
u
∑
v
∈
s
o
n
u
b
v
)
×
f
u
=
(
k
u
+
1
−
k
u
−
e
u
d
u
∑
v
∈
s
o
n
u
a
v
)
×
f
1
+
1
−
k
u
−
e
u
d
u
×
f
f
a
+
1
−
k
u
−
e
u
d
u
∑
v
∈
s
o
n
u
c
v
+
(
1
−
k
u
−
e
u
)
(1-\frac{1-k_u-e_u}{d_u}\sum_{v\in son_u}{b_v})×f_u=(k_u+\frac{1-k_u-e_u}{d_u}\sum_{v\in son_u}{a_v})×f_1+\frac{1-k_u-e_u}{d_u}×f_{fa}+\frac{1-k_u-e_u}{d_u}\sum_{v\in son_u}{c_v}+(1-k_u-e_u)
(1−du1−ku−euv∈sonu∑bv)×fu=(ku+du1−ku−euv∈sonu∑av)×f1+du1−ku−eu×ffa+du1−ku−euv∈sonu∑cv+(1−ku−eu)
于是有
a
u
=
k
u
+
1
−
k
u
−
e
u
d
u
∑
v
∈
s
o
n
u
a
v
1
−
1
−
k
u
−
e
u
d
u
∑
v
∈
s
o
n
u
b
v
a_u=\frac{k_u+\frac{1-k_u-e_u}{d_u}\sum_{v\in son_u}{a_v}}{1-\frac{1-k_u-e_u}{d_u}\sum_{v\in son_u}{b_v}}
au=1−du1−ku−eu∑v∈sonubvku+du1−ku−eu∑v∈sonuav
b
u
=
1
−
k
u
−
e
u
d
u
1
−
1
−
k
u
−
e
u
d
u
∑
v
∈
s
o
n
u
b
v
b_u=\frac{\frac{1-k_u-e_u}{d_u}}{1-\frac{1-k_u-e_u}{d_u}\sum_{v\in son_u}{b_v}}
bu=1−du1−ku−eu∑v∈sonubvdu1−ku−eu
c
u
=
1
−
k
u
−
e
u
d
u
∑
v
∈
s
o
n
u
c
v
+
(
1
−
k
u
−
e
u
)
1
−
1
−
k
u
−
e
u
d
u
∑
v
∈
s
o
n
u
b
v
c_u=\frac{\frac{1-k_u-e_u}{d_u}\sum_{v\in son_u}{c_v}+(1-k_u-e_u)}{1-\frac{1-k_u-e_u}{d_u}\sum_{v\in son_u}{b_v}}
cu=1−du1−ku−eu∑v∈sonubvdu1−ku−eu∑v∈sonucv+(1−ku−eu)
然后树形dp O ( n ) O(n) O(n)递推即可
#include<cstdio>
#include<cstring>
using namespace std;
constexpr int N=10010;
constexpr double eps=1e-10;
int h[N],e[2*N],ne[2*N],idx;
void add(int a,int b){e[idx]=b,ne[idx]=h[a],h[a]=idx++;}
int d[N],n;
double K[N],E[N],T[N],A[N],B[N],C[N];
int sgn(double x)
{
if(fabs(x)<eps) return 0;
if(x<0) return -1;
return 1;
}
bool dfs(int u,int fa)
{
int m=d[u];
A[u]=K[u];
B[u]=T[u]/m;
C[u]=T[u];
double temp=0;
for(int i=h[u];i!=-1;i=ne[i])
{
int v=e[i];
if(v==fa) continue;
if(!dfs(v,u)) return 0;
A[u]+=T[u]/m*A[v];
temp+=T[u]/m*B[v];
C[u]+=T[u]/m*C[v];
}
if(!sgn(1.0-temp)) return 0;
A[u]/=(1-temp);
B[u]/=(1-temp);
C[u]/=(1-temp);
return 1;
}
int main()
{
int TT;
scanf("%d",&TT);
for(int ca=1;ca<=TT;ca++)
{
scanf("%d",&n);
memset(h,-1,sizeof(int)*(n+1));idx=0;
memset(d,0,sizeof(int)*(n+1));
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v),add(v,u);
d[u]++,d[v]++;
}
for(int i=1;i<=n;i++)
{
scanf("%lf%lf",&K[i],&E[i]);
K[i]/=100;
E[i]/=100;
T[i]=1-K[i]-E[i];
}
if(dfs(1,0)&&sgn(1.0-A[1]))
printf("Case %d: %.10f\n",ca,C[1]/(1-A[1]));
else
printf("Case %d: impossible\n",ca);
}
return 0;
}
太秒了吧!!!
本文介绍了一种解决迷宫问题的高效算法,通过树形DP技术优化了从任意节点到达终点的期望步数计算,实现了O(n)的时间复杂度。
&spm=1001.2101.3001.5002&articleId=114358020&d=1&t=3&u=fc3cc8dfbbab44c0aadeea042fe6e473)
451

被折叠的 条评论
为什么被折叠?



