题目
3036:绿豆蛙的归宿
TimeLimit:2Sec
MemoryLimit:128MB
Description
随着新版百度空间的下线,Blog宠物绿豆蛙完成了它的使命,去寻找它新的归宿。
给出一个有向无环的连通图,起点为
1
终点为
到达每一个顶点时,如果有
K
条离开该点的道路,绿豆蛙可以选择任意一条道路离开该点,并且走向每条路的概率为
现在绿豆蛙想知道,从起点走到终点的所经过的路径总长度期望是多少?
Input
第一行:两个整数
N,M
,代表图中有
N
个点,
第二行到第
M+1
行:每行
3
个整数
Output
从起点到终点路径总长度的期望值,四舍五入保留两位小数。
SampleInput
4 4
1 2 1
1 3 2
2 3 3
3 4 4
SampleOutput
7.00
HINT
对于100%的数据:N≤100000,M≤2N
题解
我可以说这是一道裸的期望DP吗
这题其实就是一道裸的期望DP
首先题面有误,所有点都能走到终点,不然就
INF
了。
接着正式开始写题解
那我刚刚在干什么
这道题目是DAG上求期望,它就是一道裸的期望DP。
因为我只会这么做
f(i)
表示
i
到
e(i,j)
表示
i
到
因为每一个
j
有
记住这是DAG上的DP,所以要按照拓扑顺序逆推。
总时间复杂度为
O(n)
。
总结
DAG上的DP有各种各样的类型,期望DP是较常见的一种。对于DAG上的DP,需要按照拓扑顺序,选择顺推或逆推转移。
标程
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=100005;
int n, m, top;
double f[N];
bool vis[N];
int d[N];
int h[N];
struct edge{
int v, w, nxt;
}e[N<<1];
void add(int u, int v, int w)
{
e[++top].v=v;
e[top].w=w;
e[top].nxt=h[u];
h[u]=top;
}
void dfs(int u)
{
vis[u]=1;
for (int i=h[u]; i; i=e[i].nxt)
{
int v=e[i].v;
if (!vis[v]) dfs(v);
f[u]+=f[v]+e[i].w;
}
if (d[u]) f[u]/=d[u];
}
void work()
{
scanf("%d%d", &n, &m);
while (m--)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add(u, v, w);
d[u]++;
}
dfs(1);
printf("%0.2lf\n", f[1]);
}
int main()
{
work();
return 0;
}