2488 绿豆蛙的归宿

提交次数:2

难度:提高-

涉及知识:拓扑排序/期望

oj:codevs

题目描述 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

 代码:

 1 #include<iostream>
 2 #include<vector>
 3 #include<queue>
 4 #include<cstdio>
 5 using namespace std;
 6 struct edge{
 7     int u, w;
 8     edge(int uu, int ww):u(uu), w(ww){}
 9 };
10 vector<vector<edge> >v(100005);
11 queue<int>q;
12 int in[100005]; //每个点的入度 
13 double p[100005]; //走到每个点的概率 Possibility 
14 int n, m;
15 double ans;
16 
17 int main(){
18     int i;
19     cin>>n>>m;
20     for(i = 1; i <= m; i++){
21         int a, b, c;
22         cin>>a>>b>>c;
23         v[a].push_back(edge(b, c));
24         in[b]++;
25     }
26     q.push(1);
27     p[1] = 1;
28 while(!q.empty()){
29         int node = q.front();
30         q.pop();
31         if(node == n) break;
32         for(i = 0; i < v[node].size(); i++){
33             int s = v[node].size();
34             edge next = v[node][i];
35             double k= double(p[node])/double(s);
36             p[next.u] += k;
37             in[next.u]--;
38             ans += double(next.w)*k;
39             if(in[next.u]==0){
40                 q.push(next.u);
41             } 
42         }
43     }
44     printf("%.2lf
",ans);
45     return 0;
46 }

备注:

昨天上课时说到拓扑排序,老师随手在codevs上按题目分类搜的题(反正一共就两道),一道裸的拓扑排序。难点在于。。期望orz 最开始对这道题要求的期望完全理解错了

第一次提交忘了改输出格式是输出两位小数。

注意标黄的几行,改了好几次才改对,逻辑没弄清楚,现在梳理一下。

扩展到一个点后计算到达这个点的概率p[i],方法是这个点原本的概率(因为也可能在之前从别的点扩展到它)+走到上一个点的概率p[node]/上一个点的出度,这时因为已经开始删边了,相当于已经走了那几条边,所以要算对ans的贡献,怎么算呢?

边长*(走到上一个点的概率/上一个点的出度),这块似乎有点绕,但其实也很显然。走这条边的概率和走到这条边连的下一个点的概率没有直接关系(原因同上,点的概率要累加)

这样看似乎就是一道很简单的题。。。以后要先想清楚再写,写完再改又废时间又有风险。。

原文地址:https://www.cnblogs.com/fangziyuan/p/7017718.html