给出一个有向无环的连通图,起点为 1,终点为 N,每条边都有一个长度。
数据保证从起点出发能够到达图中所有的点,图中所有的点也都能够到达终点。
绿豆蛙从起点出发,走向终点。
到达每一个顶点时,如果有 K 条离开该点的道路,绿豆蛙可以选择任意一条道路离开该点,并且走向每条路的概率为 1/K。
现在绿豆蛙想知道,从起点走到终点所经过的路径总长度的期望是多少?
输入格式
第一行: 两个整数 N,M,代表图中有 N 个点、M 条边。
第二行到第 1+M 行: 每行 3 个整数 a,b,c,代表从 a 到 b 有一条长度为 c 的有向边。
输出格式
输出从起点到终点路径总长度的期望值,结果四舍五入保留两位小数。
数据范围
1≤N≤105,
1≤M≤2N
输入样例:
4 4
1 2 1
1 3 2
2 3 3
3 4 4
输出样例:
7.00
cpp
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
const int N = 100010, M = 200010;
int h[N], e[M], w[M], ne[M], idx;
int dout[N], d[N];
double f[N];
void add(int a, int b, int c)
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;
}
void dfs(int u)
{
queue<int> q;
q.push(u);
while(q.size())
{
int t = q.front();
q.pop();
for(int i = h[t]; ~i; i = ne[i])
{
int j = e[i];
f[j] += (w[i] + f[t]) / (double)dout[j];
d[j] ++;
if(d[j] == dout[j])q.push(j);
}
}
}
int main()
{
IOS
int n, m;
cin >> n >> m;
memset(h, -1, sizeof h);
while(m --)
{
int a, b, c;
cin >> a >> b >> c;
add(b, a, c);
dout[a] ++;
}
f[n] = 0;
dfs(n);
printf("%.2lf", f[1]);
return 0;
}
E(aX + bY) = aE(X) + bE(Y);
每个点的期望是k个(下一个点的期望+到下一个点的路径长度)相加除k,从最后一个点开始算。