题目链接:https://nanti.jisuanke.com/t/41301
每个点概率相等的转移到下一个点或停在原地,转移的消耗为当前的时间。
先考虑对于每个点到达终点的期望天数,设x为点i的出边数
d
a
y
[
i
]
=
∑
i
→
j
d
a
y
[
j
]
+
1
x
+
1
+
d
a
y
[
i
]
+
1
x
+
1
=
∑
i
→
j
d
a
y
[
j
]
x
+
1
+
d
a
y
[
i
]
x
+
1
+
1
d
a
y
[
i
]
=
∑
i
→
j
d
a
y
[
j
]
x
+
x
+
1
x
\begin{aligned} day[i] &= \sum_{i\rightarrow j}\frac{day[j]+1}{x+1} +\frac{day[i]+1}{x+1} \\ &= \sum_{i\rightarrow j}\frac{day[j]}{x+1} +\frac{day[i]}{x+1} +1\\ \end{aligned}\\ day[i]=\sum_{i\rightarrow j}\frac{day[j]}{x} + \frac{x+1}{x}
day[i]=i→j∑x+1day[j]+1+x+1day[i]+1=i→j∑x+1day[j]+x+1day[i]+1day[i]=i→j∑xday[j]+xx+1
计算期望消耗的方法与计算期望天数的方法相同(移动一步增加一天,增加当前天数的消耗)
c
o
s
t
[
i
]
=
∑
i
→
j
c
o
s
t
[
j
]
+
d
a
y
[
j
]
+
1
x
+
1
+
c
o
s
t
[
i
]
+
d
a
y
[
i
]
+
1
x
+
1
=
∑
i
→
j
c
o
s
t
[
j
]
x
+
1
+
∑
i
→
j
d
a
y
[
j
]
x
+
1
+
c
o
s
t
[
i
]
x
+
1
+
d
a
y
[
i
]
x
+
1
+
1
=
∑
i
→
j
c
o
s
t
[
j
]
x
+
1
+
(
x
x
+
1
d
a
y
[
i
]
−
1
)
+
c
o
s
t
[
i
]
x
+
1
+
d
a
y
[
i
]
x
+
1
+
1
=
∑
i
→
j
c
o
s
t
[
j
]
x
+
1
+
c
o
s
t
[
i
]
x
+
1
+
d
a
y
[
i
]
c
o
s
t
[
i
]
=
∑
i
→
j
c
o
s
t
[
j
]
x
+
(
x
+
1
)
d
a
y
[
i
]
x
\begin{aligned} cost[i] &= \sum_{i\rightarrow j}\frac{cost[j]+day[j]+1}{x+1} +\frac{cost [i]+day[i]+1}{x+1} \\ &= \sum_{i\rightarrow j}\frac{cost[j]}{x+1}+ \sum_{i\rightarrow j}\frac{day[j]}{x+1}+\frac{cost[i]}{x+1} +\frac{day[i]}{x+1} +1\\ &= \sum_{i\rightarrow j}\frac{cost[j]}{x+1}+(\frac{x}{x+1}day[i]-1)+\frac{cost[i]}{x+1} +\frac{day[i]}{x+1} +1\\ &=\sum_{i\rightarrow j}\frac{cost[j]}{x+1}+\frac{cost[i]}{x+1} +day[i] \\ \end{aligned}\\ cost[i]=\sum_{i\rightarrow j}\frac{cost[j]}{x} + \frac{(x+1)day[i]}{x}
cost[i]=i→j∑x+1cost[j]+day[j]+1+x+1cost[i]+day[i]+1=i→j∑x+1cost[j]+i→j∑x+1day[j]+x+1cost[i]+x+1day[i]+1=i→j∑x+1cost[j]+(x+1xday[i]−1)+x+1cost[i]+x+1day[i]+1=i→j∑x+1cost[j]+x+1cost[i]+day[i]cost[i]=i→j∑xcost[j]+x(x+1)day[i]
注意转移的时候按拓扑序倒序
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000500
#define INF 0x3f3f3f
#define ll long long
#define cin(x) scanf("%d",&x)
#define cout(x) printf("%d\n",x)
double day[maxn],ans[maxn];
ll T, n, m, u, v;
ll z1,nxt1[maxn],fir1[maxn], cnt1[maxn], b[maxn] ,nn;
ll z2,nxt2[maxn],fir2[maxn], cnt2[maxn];
struct nodes{
ll u,v;
}edges1[maxn],edges2[maxn];
void link1(ll u,ll v){
edges1[++z1].u=u;
edges1[z1].v=v;
cnt1[v]++;
nxt1[z1]=fir1[u];
fir1[u]=z1;
}
void link2(ll u,ll v){
edges2[++z2].u=u;
edges2[z2].v=v;
cnt2[u]++;
nxt2[z2]=fir2[v];
fir2[v]=z2;
}
int main(){
cin(T);
while(T--) {
memset(ans, 0.0, sizeof(ans));
memset(day, 0.0, sizeof(day));
memset(cnt1, 0, sizeof(cnt1));
memset(cnt2, 0, sizeof(cnt2));
memset(fir1, 0, sizeof(fir1));
memset(fir2, 0, sizeof(fir2));
memset(nxt1, 0, sizeof(nxt1));
memset(nxt2, 0, sizeof(nxt2));
memset(b, 0, sizeof(b));
scanf("%lld%lld", &n, &m);
z1 = 0,z2 = 0,nn = n;
for(int i = 1; i <= m; i++) {
scanf("%lld%lld", &u, &v);
link1(u, v);
link2(u, v);
}
queue<int> que;
for(int i=1;i<=n;i++) if(!cnt1[i]) que.push(i);
while(!que.empty()){
int head=que.front();
b[nn--]=head;
int tmp = head;
que.pop();
for(int i=fir1[head];i;i=nxt1[i]){
int v=edges1[i].v;
cnt1[v]--;
if(!cnt1[v]){
que.push(v);
}
}
}
day[n]=0;
for(int j=1;j<=n;j++){
int tail = b[j];
if(tail!=n){
day[tail]+=double(cnt2[tail]+1);
day[tail]/= cnt2[tail];
}
for(int i=fir2[tail];i;i=nxt2[i]){
int u=edges2[i].u;
day[u] += day[tail];
}
}
ans[n]=0;
for(int j=1;j<=n;j++){
int tail = b[j];
if(tail!=n){
ans[tail] += day[tail]*double(cnt2[tail]+1);
ans[tail] /= cnt2[tail];
}
for(int i=fir2[tail];i;i=nxt2[i]){
int u=edges2[i].u;
ans[u] += ans[tail];
}
}
printf("%.2f\n", ans[1]);
}
return 0;
}