题目链接
在做这道题之前看一个简化版:绿豆蛙的归宿
设
F
[
x
]
F[x]
F[x] 表示从
x
x
x 走到终点所经过的路径的期望长度。若从
x
x
x 出发有
k
k
k 条边,分别到达
y
1
,
y
2
.
.
.
y
k
y_1,y_2...y_k
y1,y2...yk ,边长分别为
z
1
,
z
2
.
.
.
z
k
z_1,z_2...z_k
z1,z2...zk ,则根据数学期望的定义和性质,有:
F
[
x
]
=
1
k
∗
∑
i
=
1
k
(
F
[
y
i
]
+
z
i
)
F[x]=\frac{1}{k}*\sum_{i=1}^k(F[y_i]+z_i)
F[x]=k1∗i=1∑k(F[yi]+zi)
就可以将边取反然后用拓扑排序解决。
现在这道题在上面这道题的基础上相当于将边长设置为 1 ,然后多了一个每次多走一条边的花费。
每个点到
n
n
n 点的距离相当于:
F
d
a
y
[
i
]
=
1
d
e
g
[
i
]
+
1
∗
∑
j
=
1
d
e
g
[
i
]
(
F
d
a
y
[
i
]
+
1
)
+
1
d
e
g
[
i
]
+
1
∗
(
F
d
a
y
[
i
]
+
1
)
F_{day}[i]=\frac{1}{deg[i]+1}*\sum_{j=1}^{deg[i]}(F_{day}[i]+1)+\frac{1}{deg[i]+1}*(F_{day}[i]+1)
Fday[i]=deg[i]+11∗j=1∑deg[i](Fday[i]+1)+deg[i]+11∗(Fday[i]+1)化简之后:
F
d
a
y
[
i
]
=
1
d
e
g
[
i
]
∗
∑
j
=
1
d
e
g
[
i
]
F
d
a
y
[
i
]
+
1
d
e
g
[
i
]
+
1
F_{day}[i]=\frac{1}{deg[i]}*\sum_{j=1}^{deg[i]}F_{day}[i]+\frac{1}{deg[i]}+1
Fday[i]=deg[i]1∗j=1∑deg[i]Fday[i]+deg[i]1+1
每个点到
n
n
n 点的花费相当于:
F
c
o
s
t
[
i
]
=
1
d
e
g
[
i
]
+
1
∗
∑
j
=
1
d
e
g
[
i
]
(
F
c
o
s
t
[
i
]
+
F
d
a
y
[
i
]
)
+
1
d
e
g
[
i
]
+
1
∗
(
F
c
o
s
t
[
i
]
+
F
d
a
y
[
i
]
)
F_{cost}[i]=\frac{1}{deg[i]+1}*\sum_{j=1}^{deg[i]}(F_{cost}[i]+F_{day}[i])+\frac{1}{deg[i]+1}*(F_{cost}[i]+F_{day}[i])
Fcost[i]=deg[i]+11∗j=1∑deg[i](Fcost[i]+Fday[i])+deg[i]+11∗(Fcost[i]+Fday[i])化简后:
F
c
o
s
t
[
i
]
=
1
d
e
g
[
i
]
∗
∑
j
=
1
d
e
g
[
i
]
F
c
o
s
t
[
i
]
+
F
d
a
y
[
i
]
d
e
g
[
i
]
+
F
d
a
y
[
i
]
F_{cost}[i]=\frac{1}{deg[i]}*\sum_{j=1}^{deg[i]}F_{cost}[i]+\frac{F_{day}[i]}{deg[i]}+F_{day}[i]
Fcost[i]=deg[i]1∗j=1∑deg[i]Fcost[i]+deg[i]Fday[i]+Fday[i]
由于我太菜,拓扑排序的版本我写的一直不对,改成 dfs 的写法之后就对了,要记得记忆化,不然会超时。
简化版代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define PI acos(-1.0)
#define INF 0x3f3f3f3f3f3f3f3f
#define P pair<double, int>
#define debug(x) cout << (#x) << ": " << (x) << " "
#define fastio ios::sync_with_stdio(false), cin.tie(0)
const int mod = 1e9 + 7;
const int M = 1000000 + 10;
const int N = 1000000 + 10;
int n, m, a, b;
double c;
vector<P> G[N];
int du[N], deg[N];
double f[N];
signed main()
{
scanf("%d %d", &n, &m);
for(int i = 1; i <= m; i ++) {
scanf("%d %d %lf", &a, &b, &c);
G[b].push_back(P{c, a});
du[a] ++, deg[a] ++;
}
queue<int> que;
que.push(n);
while(que.size()) {
int now = que.front();
que.pop();
for(int i = 0; i < G[now].size(); i ++) {
f[G[now][i].second] += (f[now] + G[now][i].first) / deg[G[now][i].second];
du[G[now][i].second] --;
if(!du[G[now][i].second]) que.push(G[now][i].second);
}
}
printf("%.2lf\n", f[1]);
return 0;
}
/*
Rejoicing in hope, patient in tribulation .
*/
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define PI acos(-1.0)
#define INF 0x3f3f3f3f3f3f3f3f
#define P pair<int, int>
#define debug(x) cout << (#x) << ": " << (x) << " "
#define fastio ios::sync_with_stdio(false), cin.tie(0)
const int mod = 1e9 + 7;
const int M = 1000000 + 10;
const int N = 400000 + 10;
int t, n, m, a, b;
double f_day[N], f_cost[N];
int deg[N];
vector<int> G[N];
void init()
{
for(int i = 1; i <= n; ++ i) {
f_day[i] = f_cost[i] = deg[i] = 0;
G[i].clear();
}
}
double dfs_day(int now)
{
if(now == n) return 0;
if(f_day[now]) return f_day[now];
double sum = 0;
for(int i = 0; i < G[now].size(); ++ i) {
sum += dfs_day(G[now][i]);
}
return f_day[now] = sum / deg[now] + 1 + 1.0 / deg[now];
}
double dfs_cost(int now)
{
if(now == n) return 0;
if(f_cost[now]) return f_cost[now];
double sum = 0;
for(int i = 0; i < G[now].size(); ++ i) {
sum += dfs_cost(G[now][i]);
}
return f_cost[now] = sum / deg[now] + f_day[now] + f_day[now] / deg[now];
}
signed main()
{
scanf("%d", &t);
while(t --) {
scanf("%d %d", &n, &m);
init();
for(int i = 1; i <= m; ++ i) {
scanf("%d %d", &a, &b);
G[a].push_back(b);
deg[a] ++;
}
dfs_day(1);
dfs_cost(1);
printf("%.2f\n", f_cost[1]);
}
return 0;
}
/*
Rejoicing in hope, patient in tribulation .
*/