# ABC144_F Fork in the Road 期望DP
## 题意
有$N$个点,$M$条有向边,有向边表示$s_i -> t_i$,且满足$s_i < t_i$
每到一个点会等概率得选择一条边移动
在开始前会删除一条边(或者不删)来最小化到$n$的期望步数
问移动到$N$号点的期望步数
$$
2\leq N\leq600\\
N - 1\leq M \leq \frac{N(N-1)}{2}
$$
## 分析
有一些显然的结论
设$F[i]$表示从$i$号点走到$n$号点的期望步数,则有
$$
F[n] = 0\\
F[i] = avg(F[j]) + 1 (i,j)有边
$$
这样就构成方程组高斯消元即可
注意到此题给出$s_i < t_i$
即保证了总是从小点走到大点,因此可以直接DP
那么删哪条边呢?
从转移方程来看,我们显然希望删除掉最大的$F[j]$来最小化当前的期望,而此题的$n$比较小,因此不妨枚举删除$i$出发的边,贪心删除最大期望的边
复杂度$O(n^2m)$
## 代码
```c++
double dp[605];
vector<int> e[maxn];
int n,m;
double cal(int x){
for(int i = n - 1;i >= 1;i--){
dp[i] = 1;
double mx = -1;
double t = 0;
for(auto v:e[i]){
if(dp[v] > mx) mx = dp[v],t = v;
}
if(i == x && e[i].size() != 1)
for(auto v:e[i]) {
if(v == t) continue;
dp[i] += dp[v] / (e[i].size() - 1);
}
else
for(auto v:e[i])
dp[i] += dp[v] / e[i].size();
}
return dp[1];
}
int main(){
n = rd();
m = rd();
for(int i = 1;i <= m;i++){
int x = rd();
int y = rd();
e[x].push_back(y);
}
dp[n] = 0;
double ans = 1e18;
for(int i = 1;i < n;i++){
ans = min(ans,cal(i));
}
printf("%.10f",ans);
}