藍書(演算法競賽進階指南)刷題記錄——CH3802 綠豆蛙的歸宿(DAG期望DP)
阿新 • • 發佈:2018-11-10
題目:CH3802.
題目大意:給定一張有向無環圖,一直蛙要從點1走到點n,它每次會等概率從一個點經過一條出邊走到下一個點,求從點1走到點n的期望路徑長度.
我們很容易看出這是一個期望DP.
那麼我們設狀態f[i]為從點1到點i時的期望路徑長度.
但是我們發現狀態轉移方程就十分不自然了,寫起來總感覺很彆扭.
所以我們換一個狀態,設狀態f[i]為從點i到點N的期望路徑長度.
我們設點i的出邊數量為,所有出邊的終點為,邊權為,那麼方程就是:.
那麼我們只需要建一張反圖,在反圖上跑DP即可.
程式碼如下:
#include<bits/stdc++.h> using namespace std; #define Abigail inline void typedef long long LL; const int N=100000; int n,m; struct side{ int y,next,v; }e[N*2+9]; int lin[N+9],top,deg[N+9],out[N+9]; queue<int>q; double f[N+9]; void ins(int x,int y,int v){ e[++top].y=y;e[top].v=v; e[top].next=lin[x]; lin[x]=top; } Abigail into(){ scanf("%d%d",&n,&m); int x,y,v; for (int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&v); ins(y,x,v); deg[x]++;out[x]++; } } Abigail work(){ q.push(n); while (!q.empty()){ int t=q.front();q.pop(); for (int i=lin[t];i;i=e[i].next){ f[e[i].y]+=(f[t]+1.0*e[i].v)/deg[e[i].y]; out[e[i].y]--; if (!out[e[i].y]) q.push(e[i].y); } } } Abigail outo(){ printf("%.2lf\n",f[1]); } int main(){ into(); work(); outo(); return 0; }