【BZOJ】3036: 绿豆蛙的归宿
Description
随着新版百度空间的下线,Blog宠物绿豆蛙完成了它的使命,去寻找它新的归宿。
给出一个有向无环的连通图,起点为1终点为N,每条边都有一个长度。绿豆蛙从起点出发,走向终点。
到达每一个顶点时,如果有K条离开该点的道路,绿豆蛙可以选择任意一条道路离开该点,并且走向每条路的概率为 1/K 。
现在绿豆蛙想知道,从起点走到终点的所经过的路径总长度期望是多少?
Input
第一行: 两个整数 N M,代表图中有N个点、M条边
第二行到第 1+M 行: 每行3个整数 a b c,代表从a到b有一条长度为c的有向边
Output
从起点到终点路径总长度的期望值,四舍五入保留两位小数。
Sample Input
4 4
1 2 1
1 3 2
2 3 3
3 4 4
1 2 1
1 3 2
2 3 3
3 4 4
Sample Output
7.00
HINT
对于100%的数据 N<=100000,M<=2*N
题解:
概率dp……还是写得少啊。
dp[i]表示搜索到第i个点的答案。先预处理出来每个点的出度。然后像跑图一样跑一边dfs就行了。一个点的答案为子树的答案+这个点与儿子之间的边权贡献出来的答案。
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; const int MAXN = 100001; const int MAXM = 200001; struct xx { int from, to, w, nxt; }e[MAXM]; int n, m, cnt, head[MAXM]; bool visit[MAXN]; double dp[MAXN]; int chu[MAXN]; inline void add(int x, int y, int z) { cnt++; e[cnt].from = x; e[cnt].to = y; e[cnt].w = z; e[cnt].nxt = head[x]; head[x] = cnt; chu[x]++; } void dfs(int x) { int i; visit[x] = true; for (i = head[x]; i; i = e[i].nxt) { if (visit[e[i].to] == false) dfs(e[i].to); dp[x] += dp[e[i].to] + e[i].w; } if (chu[x] != 0) dp[x] = dp[x] / (chu[x]*1.0)*1.0; } int main(int argc, char *argv[]) { int i, j, x, y,z; scanf("%d%d", &n, &m); for (i = 1; i <= m; i++) { scanf("%d%d%d", &x, &y, &z); add(x, y, z); } dfs(1); printf("%.2f\n", dp[1]); return 0; }
叶子的离去,是风的追求,还是树的不挽留?