首页 > 代码库 > 2488 绿豆蛙的归宿
2488 绿豆蛙的归宿
codevs——2488 绿豆蛙的归宿
时间限制: 1 s
空间限制: 64000 KB
题目等级 : 黄金 Gold
题目描述 Description
随着新版百度空间的上线,Blog宠物绿豆蛙完成了它的使命,去寻找它新的归宿。
给出一个有向无环图,起点为1终点为N,每条边都有一个长度,并且从起点出发能够到达所有的点,所有的点也都能够到达终点。绿豆蛙从起点出发,走向终点。
到达每一个顶点时,如果有K条离开该点的道路,绿豆蛙可以选择任意一条道路离开该点,并且走向每条路的概率为 1/K 。
现在绿豆蛙想知道,从起点走到终点的所经过的路径总长度期望是多少?
输入描述 Input Description
第一行: 两个整数 N M,代表图中有N个点、M条边
第二行到第 1+M 行: 每行3个整数 a b c,代表从a到b有一条长度为c的有向边
输出描述 Output Description
从起点到终点路径总长度的期望值,四舍五入保留两位小数。
样例输入 Sample Input
4 4
1 2 1
1 3 2
2 3 3
3 4 4
样例输出 Sample Output
7.00
数据范围及提示 Data Size & Hint
对于20%的数据 N<=100
对于40%的数据 N<=1000
对于60%的数据 N<=10000
对于100%的数据 N<=100000,M<=2*N
来源:Nescafe 19
分类标签 Tags 点此展开
动态规划 拓扑排序 图论
思路:
这个题说是概率dp,但是只用一个完美的拓扑排序完全就可以过。
其实这道题概率dp完全可以过,大佬们可以尝试一下,不懂的可以看这位大佬的博客。
蒟蒻由于不会概率dp就只好用拓扑排序水过了。。。。
我们下面来说说拓扑排序的思路。
我们现在输入的时候与处理出每一个点的入度和初度。有人肯定要问了:处理出入度和出度有什么用啊??
这里我们用入读是来得知这个点是否应该被用拓扑排序删掉这个点。(在拓扑排序中有用就对了)
我们用一个点的出度来判断一一条路径被走的概率。(用该点的概率*该点出度的个数即为走这条边的概率)
然后我们在用一个数组储存每一条路径的概率。由于期望值是可以累加的,期望值等于这个点的边权乘这个点的概率。
这样我们就可以在最后时用每一条边的概率乘上这条边的边权。这样累加起来就是整条路径的期望值。
代码:
#include<stack>#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#define N 10000using namespace std;stack<double>q;int n,m,x,y,z,tot;double p[N],ans;int in[N],out[N],head[N];struct Edge{ int from,to,dis,next; double gl;} edge[N<<2];void add(int x,int y,int z){ tot++; edge[tot].to=y; edge[tot].dis=z; edge[tot].next=head[x]; head[x]=tot;}int main(){ scanf("%d%d",&n,&m); for(int i=1; i<=m; i++) { scanf("%d%d%d",&x,&y,&z); add(x,y,z); in[y]++; out[x]++; } p[1]=1; q.push(1); int now; while(!q.empty()) { now=q.top(); q.pop(); for(int i=head[now]; i; i=edge[i].next) { p[edge[i].to]+=p[now]*1.0/out[now]; edge[i].gl=p[now]*1.0/out[now]; in[edge[i].to]--; if(!in[edge[i].to]) q.push(edge[i].to); } } for(int i=1;i<=m;i++) ans+=edge[i].gl*edge[i].dis; printf("%.2lf",ans); return 0;}
2488 绿豆蛙的归宿
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。