#include using namespace std; const int N = 1e5 + 10, M = N << 1; // 邻接表 int h[N], e[M], ne[M], w[M], idx; void add(int a, int b, int c) { e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++; } int n, m; // n个顶点,m条边 int out[N], in[N]; // 出度,入度 double f[N], g[N]; // f:数学期望结果 g:概率 void topsort() { queue q; // 起点为1,起点的概率为100% q.push(1); g[1] = 1.0; f[1] = 0.0; // DAG,执行拓扑序,以保证计算的顺序正确,确保递归过程中,前序数据都已处理完毕 while (q.size()) { auto u = q.front(); q.pop(); for (int i = h[u]; ~i; i = ne[i]) { // 枚举的是每边相邻边 int v = e[i]; // 此边,一端是t,另一端是j // 此边边条w[i] f[v] += (f[u] + w[i] * g[u]) / out[u]; g[v] += g[u] / out[u]; // g[j]也需要概率累加 // 拓扑序的标准套路 in[v]--; if (!in[v]) q.push(v); } } } int main() { // 初始化邻接表 memset(h, -1, sizeof h); cin >> n >> m; while (m--) { int a, b, c; cin >> a >> b >> c; add(a, b, c); // 维护出度,入度 out[a]++, in[b]++; } // 拓扑序 topsort(); // 正向递推,输出结果,保留两位小数 printf("%.2lf", f[n]); return 0; }