1. 程式人生 > >洛谷P4316 綠豆蛙的歸宿【期望DP】

洛谷P4316 綠豆蛙的歸宿【期望DP】

時空限制 1000ms / 128MB

題目描述

給出一個有向無環圖,起點為1終點為N,每條邊都有一個長度,並且從起點出發能夠到達所有的點,所有的點也都能夠到達終點。綠豆蛙從起點出發,走向終點。 到達每一個頂點時,如果有K條離開該點的道路,綠豆蛙可以選擇任意一條道路離開該點,並且走向每條路的概率為 1/K 。 現在綠豆蛙想知道,從起點走到終點的所經過的路徑總長度期望是多少?

輸入格式:

第一行: 兩個整數 N M,代表圖中有N個點、M條邊 第二行到第 1+M 行: 每行3個整數 a b c,代表從a到b有一條長度為c的有向邊

輸出格式:

從起點到終點路徑總長度的期望值,四捨五入保留兩位小數。

說明

對於20%的資料 N<=100 對於40%的資料 N<=1000 對於60%的資料 N<=10000 對於100%的資料 N<=100000,M<=2*N

題目分析

dp[u]dp[u]表示uunn的期望路徑長度uu出發能達到的點集為{vi}\{v_i\} 那麼dp[u]=1k(vi+dis(u,vi))dp[u]=\frac{1}{k}\sum (v_i+dis(u,v_i))k為uu的出度 由於是有向無環圖,所以直接在DAG上記搜即可

#include<iostream>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio> using namespace std; typedef long long lt; typedef double dd; int read() { int f=1,x=0; char ss=getchar(); while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();} while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();} return f*x; } const int maxn=
100010; int n,m; struct node{int v,dis,nxt;}E[maxn<<1]; int head[maxn],tot; int deg[maxn]; dd dp[maxn]; void add(int u,int v,int dis) { E[++tot].nxt=head[u]; E[tot].v=v; E[tot].dis=dis; head[u]=tot; } dd DP(int u) { if(u==n) return dp[u]=0; if(dp[u]) return dp[u]; dd res=0; for(int i=head[u];i;i=E[i].nxt) { int v=E[i].v; res+=DP(v)+E[i].dis; } return dp[u]=res/deg[u]; } int main() { n=read();m=read(); for(int i=1;i<=m;++i) { int u=read(),v=read(),dis=read(); add(u,v,dis); deg[u]++; } DP(1); printf("%.2lf",dp[1]); return 0; }