给出一个有向无环的连通图,起点为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


dp方程不难推出。我们令dp[x]为x到点n的期望步数。

对于x能到达所有的点y的k条路径

dp[x] = sigma(dp[y] + w) / k ,

所以我们直接跑一遍拓扑,在拓扑中dp即可。


AC代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
vector<int> v1[N],v2[N];
int n,m,d[N],k[N];
double dp[N];
void top_sort(){
    queue<int> q;   q.push(n);
    while(q.size()){
        int u=q.front();    q.pop();
        for(int i=0;i<v1[u].size();i++){
            int w=v2[u][i],to=v1[u][i];    dp[to]+=w+dp[u];
            if(--d[to]==0){
                dp[to]/=k[to];  q.push(to);
            }
        }
    }
}
int main(){
    cin>>n>>m;
    for(int i=1,a,b,c;i<=m;i++){
        scanf("%d %d %d",&a,&b,&c),v1[b].push_back(a),v2[b].push_back(c);
        d[a]++; k[a]++;
    }   
    top_sort();
    printf("%.2lf\n",dp[1]);
    return 0;
}