路径长度
题目链接:ybt金牌导航1-1-1 / ybt高效进阶6-6-3
题目大意
在一个有向无环图中,从 1 出发到 n,问你所经过的路径总长度期望。
(所有点都可以到 n 点,1 点可以到所有点)
思路
这一道题基本算可以说是一道期望模板题了。
设 d p i dp_i dpi 为从 i i i 点走到 n n n 点所经过的路径总长度期望。
就直接每次找没有出度的地方,然后算它原来图中可以走到的每一条边,所能给它的期望,然后再把能走向它的边删了。
(因为这这个图中没有初度,就说明要么真的没有初度,要么它能走到的点都已经算出了期望,就可以算它的期望了)
这与怎么算期望,就是这个式子:
d
p
i
=
∑
e
∈
s
o
n
i
d
p
e
.
t
o
+
e
.
x
∣
s
o
n
i
∣
dp_i=\sum\limits_{e\in son_i}{\dfrac{dp_{e.to}+e.x}{|son_i|}}
dpi=e∈soni∑∣soni∣dpe.to+e.x
就是说等概率走到它能走到的每一个点,然后从那个点走到终点的这个期望我们已经知道,然后加上这条边的距离在除以走这条边的概率。然后每一条边都这样,就可以得出
d
p
i
dp_i
dpi 了。
代码
#include<queue>
#include<cstdio>
using namespace std;
struct node {
int x, to, nxt;
}e[200001], be[200001];
int n, m, le[100001], KK, out[100001], tout[100001], x, y, z, now, ble[200001], KKK;
double qw[100001];
queue <int> q;
void add(int x, int y, int z) {
e[++KK] = (node){z, y, le[x]}; le[x] = KK;
out[x]++;
tout[x]++;
be[++KKK] = (node){z, x, ble[y]}; ble[y] = KKK;
}
int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; i++) {
scanf("%d %d %d", &x, &y, &z);
add(x, y, z);
}
q.push(n);
while (!q.empty()) {
now = q.front();
q.pop();
for (int i = le[now]; i; i = e[i].nxt) {//算期望
qw[now] += (qw[e[i].to] + e[i].x) / out[now];
}
for (int i = ble[now]; i; i = be[i].nxt) {
tout[be[i].to]--;
if (!tout[be[i].to]) q.push(be[i].to);//找到可以算期望的边
}
}
printf("%.2lf", qw[1]);
return 0;
}