题目描述
给出张 n 个点 m 条边的有向无环图,起点为 11,终点为 n,每条边都有一个长度,并且从起点出发能够到达所有的点,所有的点也都能够到达终点。
绿豆蛙从起点出发,走向终点。 到达每一个顶点时,如果该节点有 k 条出边,绿豆蛙可以选择任意一条边离开该点,并且走向每条边的概率为 1/k。现在绿豆蛙想知道,从起点走到终点的所经过的路径总长度期望是多少?
错误点
- 题目给出的是有向边但是按无向边做处理;
- 直接遍历每种情况导致TL
思路
1.dfs找出每条可能的路径,在抵达终点后按照其概率赋值给终点(TL)
2.先由有向无环图推出解法大概会与拓扑排序有关,再结合期望dp的解法,可倒序求出每个位置的点到终点的期望长度,这里注意转移方程的写法:dp[u] += (dp[v] + w[u][v]) / cnt;(cnt表示由u到v的边数)
代码:
#include <iostream>
#include<vector>
#include<algorithm>
#include<cstring>
#include<set>
#include<queue>
using namespace std;
struct P {
int to, v;
P(int to, int v) :to(to), v(v) {}
};
vector<P>a[100005];
int n, cnt[100005],in[100005];
double dp[100005];
int main(void) {
int m; cin >> n >> m;
while (m--) {
int u, v, w;
//倒序输入
cin >> v >> u >> w;
//单向边
a[u].push_back(P(v, w));
//v可往下走的边数
cnt[v]++;
in[v]++;
}
priority_queue<int>q; q.push(n);
//拓扑排序
while (!q.empty()) {
int x = q.top(); q.pop();
for (int i = 0; i < a[x].size(); i++) {
int w = a[x][i].to;
in[w]--;
//向上递推
dp[w] += (dp[x] + a[x][i].v) / cnt[w];
if (in[w] == 0) q.push(w);
}
}
printf_s("%.2lf\n", dp[1]);
return 0;
}
标签:cnt,终点,int,绿豆蛙,P4316,include,dp
From: https://www.cnblogs.com/markun0/p/17359478.html