首页 > 代码库 > 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 绿豆蛙的归宿