[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]);
}
posted @ 2021-08-11 19:45  fhq_treap  阅读(42)  评论(0编辑  收藏  举报