[CERC2017]Gambling Guide
考虑这种dp问题,图上可以用类最短路算法。
这类问题我们需要确定这样一个偏序关系:
\(f_x > f_x’ > f_y\),\(f_y为y来更新x\),\(f_x'为新值\)。
我们这题直接上期望dp就行。
考虑\(f_x = \frac{deg + sum}{cnt}\),\(cnt\)为周边以确定的数。
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
#define ll long long
#define N 300005
struct P{
int to,next;
}e[N << 1];
ll n,m;
ll head[N],cnt[N],hcnt,deg[N];
inline void add(int x,int y){
e[++hcnt].to = y;
e[hcnt].next = head[x];
head[x] = hcnt;
}
double f[N],sum[N];
std::priority_queue<std::pair<double,int> >QWQ;
ll vis[N];
inline void dij(){
QWQ.push(std::make_pair(0.0,n));
while(QWQ.size()){
int u = QWQ.top().second;
QWQ.pop();
if(vis[u])continue;
vis[u] = 1;
for(int i = head[u];i;i = e[i].next){
int v = e[i].to;
if(f[u] < f[v]){
sum[v] += f[u];
cnt[v] ++ ;
f[v] = (deg[v] + sum[v]) / cnt[v];
QWQ.push(std::make_pair(-f[v],v));
}
}
}
}
int main(){
std::memset(f,0x7f,sizeof(f));
scanf("%lld%lld",&n,&m);
for(int i = 1;i <= m;++i){
ll x,y;
scanf("%lld%lld",&x,&y);
add(x,y);
add(y,x);
deg[x] ++ ;
deg[y] ++ ;
}
f[n] = 0.0;
dij();
printf("%.6lf",f[1]);
}