bzoj3036 绿豆蛙的归宿

来源:互联网 发布:淘宝运营工资是多少 编辑:程序博客网 时间:2024/04/28 01:37

3036: 绿豆蛙的归宿

Time Limit: 2 Sec  Memory Limit: 128 MB
Submit: 319  Solved: 224
[Submit][Status][Discuss]

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

Source

Poetize3




概率期望DP

f[i]表示从i到n的期望长度,则状态转移方程为:

f[i]=∑(f[e[i].to]+e[i].v)/outd[i]

其中outd[i]表示i点的出度,e[i].to是与i相连的点。

一个小的总结:如果一个点的每条出边概率相同,则逆向DP更加容易求解




#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>#define F(i,j,n) for(int i=j;i<=n;i++)#define D(i,j,n) for(int i=j;i>=n;i--)#define ll long long#define maxn 100005using namespace std;int n,m,cnt,head[maxn];double f[maxn];bool vst[maxn];struct edge_type{int next,to,v;}e[maxn*2];inline int read(){int x=0,f=1;char ch=getchar();while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}inline void add_edge(int x,int y,int v){e[++cnt]=(edge_type){head[x],y,v};head[x]=cnt;}inline void dfs(int x){if (vst[x]) return;vst[x]=true;int outd=0;for(int i=head[x];i;i=e[i].next){dfs(e[i].to);f[x]+=f[e[i].to]+e[i].v;outd++;}if (!outd) return;f[x]/=outd;}int main(){n=read();m=read();F(i,1,m){int x=read(),y=read(),z=read();add_edge(x,y,z);}dfs(1);printf("%.2lf\n",f[1]);return 0;}


0 0