【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

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;
}
posted @ 2016-10-10 19:24  BeyondW  阅读(290)  评论(0编辑  收藏  举报