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