题目背景
随着新版百度空间的上线,Blog 宠物绿豆蛙完成了它的使命,去寻找它新的归宿。
题目描述
给出张 nn 个点 mm 条边的有向无环图,起点为 11,终点为 nn,每条边都有一个长度,并且从起点出发能够到达所有的点,所有的点也都能够到达终点。
绿豆蛙从起点出发,走向终点。 到达每一个顶点时,如果该节点有 kk 条出边,绿豆蛙可以选择任意一条边离开该点,并且走向每条边的概率为 \frac{1}{k}k1 。现在绿豆蛙想知道,从起点走到终点的所经过的路径总长度期望是多少?
输入格式
输入的第一行是两个整数,分别代表图的点数 nn 和边数 mm。
第 22 到第 (m + 1)(m+1) 行,每行有三个整数 u, v, wu,v,w,代表存在一条从 uu 指向 vv 长度为 ww 的有向边。
输出格式
输出一行一个实数代表答案,四舍五入保留两位小数。
输入输出样例
输入 #1
4 4 1 2 1 1 3 2 2 3 3 3 4 4
输出 #1
7.00
说明/提示
具体数据规约看题目描述。
思路
这道题是我在洛谷某用户分享的《拓扑排序》题单中遇到的,然而这不是一道拓扑排序题啊,应该要归为记忆化深度优先搜索才是,具体如下:
#include<iostream>
#include<algorithm>
#include<map>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<numeric>
#include<stack>
#include<queue>
#include<set>
#include<string>
#include<vector>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f,int_max=0x7fffffff,maxn=100005;
//首先要算所有可能的路径总期望就是算出{所有路径乘以其走的概率}之和
//所以似乎可以是直接记忆化dfs,从终点到某个点路径的总期望,然后就搞
double save[maxn];
struct edge{
int v,w;
};
vector<edge> g[maxn];
double dfs(int u)
{
if(save[u])return save[u];
double k=1.0/g[u].size();
for(auto e:g[u])
{
int v=e.v,w=e.w;
save[u]+=k*(w+dfs(v));
}
return save[u];
}
bool son[maxn];
int main()
{
//cout<<sizeof(double);//8,emmm大概还是够装的
ios_base::sync_with_stdio(0),cin.tie(0);
memset(save,0,sizeof save);
memset(son,0,sizeof son);
int n,m;
cin>>n>>m;
for(int i=0;i<m;i++)
{
int u,v,w;
cin>>u>>v>>w;
son[v]=1;
g[u].push_back({v,w});
}
for(int i=1;i<=n;i++)
{
if(!son[i])
{
cout<<fixed<<setprecision(2)<<dfs(i);
break;
}
}
return 0;
}