题意:给定一个图,从点1出发,每次通过一步 ,可以前往下一个点,也可以停留在当前点,问到达点n的最小期望步数。(最小是因为不要瞎走..为了最优的走法)
洛谷题解:查看
注意题目中的f[x]表示是从x到n的需要的期望步数,之后再有x推与x想连接的节点,所以开始我们加入的是n,访问到1结束。(开始加入1访问n是不对的..)
公式1->公式二的推导:将f[x]看做未知数,将右面分式隐藏的f[x]提出来,整理。
#include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mp make_pair #define fi first #define se second #define all(v) v.begin(),v.end() #define mem(a) memset(a,0,sizeof(a)) #define pdi pair<long double ,int> const int N = 3e5+4; const double INF =1e50+2; vector<int>V[N]; int vis[N]; int n,m; long double ans[N]; int in[N]; int cnt[N]; void dij(){ priority_queue< pdi,vector<pdi>,greater<pdi> >Q; Q.push( pdi(0,n)); while(!Q.empty()){ pdi t =Q.top(); Q.pop(); double val = t.fi; int ind =t.se; if(vis[ind])continue; vis[ind]=1; ans[ind] =val; for(auto x:V[ind]){ if(vis[x]==false){ cnt[x]++; ans[x]+=val; Q.push(mp( (in[x]+ans[x])/cnt[x] ,x)); } } } } int main(){ cin>>n>>m; for(int i=1;i<=m;++i){ int a,b; scanf("%d %d",&a,&b); V[a].pb(b); V[b].pb(a); in[a]++; in[b]++; } dij(); printf("%.10Lf ",ans[1]); return 0; }