绿豆蛙的归宿 - 期望DP

概率正着来,期望倒着推
设f(i)表示由i到n的期望路径,设u->v有一条边,则fu += (fv + w)/出边 答案为f1
为什么w不用算到fv里面呢,考虑从fv出发到n,那么fv最后概率为1
注意dfs的时候,不能重复走一个点,但是可以重复采集一个点的信息
特别注意,由于是倒推

#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
#define debug(x) cerr << #x << "=" << x << endl;
const int MAXN = 100000 + 10;
const int MAXM = 100000 * 2 + 10;
int n,m,last[MAXN],tot,et[MAXN],vis[MAXN];
double f[MAXN],pre[MAXN];
struct Edge{
    int u,v,w,to;
    Edge(){}
    Edge(int u, int v, int w, int to) : u(u), v(v), w(w), to(to) {}
}e[MAXM];
inline void add(int u, int v, int w) {
    e[++tot] = Edge(u,v,w,last[u]);
    last[u] = tot;
}
void dfs(int x) {
    if(vis[x]) return;
    vis[x] = 1;
    for(int i=last[x]; i; i=e[i].to) {
        int v = e[i].v;
        double temp = et[x];
        temp = 1/temp;
        double w = (double)e[i].w;
        dfs(v);
        f[x] += (f[v] + w);
    }
    if(et[x]) f[x] /= (double) et[x];
}
int main() {
    scanf("%d %d", &n, &m);
    for(int i=1; i<=m; i++) {
        int u,v,w;
        scanf("%d %d %d", &u, &v, &w);
        add(u,v,w);
        et[u]++;
    }
    dfs(1);
    printf("%.2f", f[1]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Fantasy_World/article/details/81512446