bzoj3036 绿豆蛙的归宿

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 100005
using 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;
}


你可能感兴趣的:(bzoj,概率DP)