绿豆蛙的归宿
Time Limit:10000MS Memory Limit:165536K
Total Submit:3 Accepted:1
Case Time Limit:1000MS
Description
给出一个有向无环的连通图,起点为1终点为N,每条边都有一个长度。绿豆蛙从起点出发,走向终点。
到达每一个顶点时,如果有K条离开该点的道路,绿豆蛙可以选择任意一条道路离开该点,并且走向每条路的概率为 1/K 。
现在绿豆蛙想知道,从起点走到终点的所经过的路径总长度期望是多少?
Input
第一行: 两个整数 N M,代表图中有N个点、M条边
第二行到第 1+M 行: 每行3个整数 a b c,代表从a到b有一条长度为c的有向边
Output
从起点到终点路径总长度的期望值,四舍五入保留两位小数。
Sample Input
4 4
1 2 1
1 3 2
2 3 3
3 4 4
Sample Output
7.00
这题题目比较弱dfs就可以过…数据也比较仁慈1可以到所有点
我则是拓扑排序然后算期望长度,记p[i]表示到i点的概率,d[i]为i的出度,r[i]为i的入度,跟新p[son]+=p [i]/d[i],ans[son]+=p[i]/d[i]*v+ans[i]/d[i]
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 1100000;
int now[maxn], son[maxn], v[maxn], pre[maxn];
int tot, d[maxn], r[maxn], n, m;
void cc(int a, int b, int c){
pre[++ tot] = now[a]; now[a] = tot;
son[tot] = b; v[tot] = c;
d[a] ++; r[b] ++;
}
void init(){
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i ++){
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
cc(a, b, c);
}
}
void work(){
static int tt, ww, h[maxn];
static double ans[maxn], p[maxn];
tt = 0, ww = 1; h[1] = 1; p[1] = 1;
while (tt != ww){
tt ++;
for (int pp = now[h[tt]]; pp; pp = pre[pp]){
p[son[pp]] += p[h[tt]] / d[h[tt]];
ans[son[pp]] += (v[pp] * p[h[tt]]+ ans[h[tt]]) / d[h[tt]];
r[son[pp]] --;
if (!r[son[pp]]) h[++ ww] = son[pp];
}
}
printf("%.2lf\n", ans[n]);
}
int main(){
init();
work();
return 0;
}