给出一个
n
≤
4
e
5
,
m
≤
5
e
5
n\leq4e5,m\leq5e5
n≤4e5,m≤5e5的有向图,并且保证起点
1
1
1是唯一的,终点
n
n
n也是唯一的,每次有等同的概率停留在原地或者走到下一个点,每次走到新的点要耗费一天的代价,走到每个点的得分是走到这个点的天数。求问最终走到终点的得分的期望。
可以拆成两部分来做。
E
1
(
u
)
E_{1}(u)
E1(u)表示从
u
u
u到终点的天数期望。u转移有
E
1
(
u
)
=
E
1
(
u
)
d
e
g
[
u
]
+
1
+
∑
E
1
(
v
)
d
e
g
[
u
]
+
1
+
1
E_{1}(u)=\frac{E_{1}(u)}{deg[u]+1}+\frac{\sum E_{1}(v)}{deg[u]+1}+1
E1(u)=deg[u]+1E1(u)+deg[u]+1∑E1(v)+1,然后再去求
E
2
(
u
)
E_{2}(u)
E2(u)表示
u
u
u到终点的的得分期望。
E
2
(
u
)
=
E
2
(
u
)
d
e
g
[
u
]
+
1
+
∑
E
2
(
v
)
d
e
g
[
u
]
+
1
+
E
1
(
u
)
E_{2}(u)=\frac{E_{2}(u)}{deg[u]+1}+\frac{\sum E_{2}(v)}{deg[u]+1}+E_{1}(u)
E2(u)=deg[u]+1E2(u)+deg[u]+1∑E2(v)+E1(u)。
记忆化搜索转移就好了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll INF=LONG_LONG_MAX;
const int N=1e5+7;
vector<int> G[N];
double dp1[N],dp2[N];
int deg[N];
int n,m;
double dfs1(int u) {
if(u==n) return 0;
if(dp1[u]) return dp1[u];
double ans=0.0;
for(auto &v:G[u]) {
ans+=dfs1(v);
}
return dp1[u]=ans/deg[u]+1.0+1.0/deg[u];
}
double dfs2(int u) {
if(u==n) return 0;
if(dp2[u]) return dp2[u];
double ans=0.0;
for(auto &v:G[u]) {
ans+=dfs2(v);
}
return dp2[u]=ans/deg[u]+dp1[u]+dp1[u]/deg[u];
}
int main() {
int T;
scanf("%d",&T);
while(T--) {
memset(dp1,0,sizeof(dp1));
memset(dp2,0,sizeof(dp2));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) {
G[i].clear();
deg[i]=0;
}
for(int i=1;i<=m;i++) {
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
deg[u]++;
}
dfs1(1);
double ans=dfs2(1);
printf("%.2lf\n",ans);
}
return 0;
}