217. 绿豆蛙的归宿

// 217. 绿豆蛙的归宿.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//


/*
https://www.acwing.com/problem/content/219/

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

#define  _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
using namespace std;

const int N = 1e5 + 10;
const int M = 2 * N;
int h[N], e[M], w[M], ne[M], idx;
int n, m;
double f[N];
int out[N];

void add(int a, int b, int l ){
	e[idx] = b, w[idx] = l, ne[idx] = h[a], h[a] = idx++;
}


double dfs(int x) {
	if (x == n) return f[x];
	if (f[x] > 1e-6) return f[x];

	double res = f[x];
	int cnt = out[x];
	for (int i = h[x]; i != -1; i = ne[i]) {
		int j = e[i]; int l = w[i];
		res += 1.0 / cnt * (dfs(j) + 1.0*l);
	}
	return res;
}



int main()
{
	memset(h, -1, sizeof h);
	memset(f, 0, sizeof f);
	cin >> n >> m;

	for (int i = 0; i < m; i++) {
		int a, b, l; cin >> a >> b >> l;
		add(a, b, l);
		out[a]++;
	}

	printf("%.2f\n",dfs(1));

	return 0;
}

posted on 2025-04-07 16:09  itdef  阅读(6)  评论(0)    收藏  举报

导航