[CERC2017]Gambling Guide

时间:2019-09-22
本文章向大家介绍[CERC2017]Gambling Guide,主要包括[CERC2017]Gambling Guide使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题目

看起来非常随机游走,但是由于我们可以停在原地,所以变得不是非常一样

\(f_x\)表示从\(x\)\(n\)的期望距离

如果我们提前知道了\(f\),那么我们随机到了一张到\(y\)的车票,发现\(f_y>f_x\),那么我们不如停在原地再随一张

所以就有

\[f_x=\frac{\sum_{(x,y)\in e}1+\min(f_x,f_y)}{d_x}=1+\frac{\sum_{(x,y)\in e}\min(f_x,f_y)}{d_x}\]

这个式子不是很好看,我们将其改写一下

\[f_x=1+\frac{\sum_{(x,y)\in e}[f_y<f_x]f_y+f_x(d-\sum_{(x,y)\in e}[f_y<f_x])}{d_x}=\frac{d_x+\sum_{(x,y)\in e}[f_y<f_x]f_y}{\sum_{(x,y)\in e}[f_y<f_x]}\]

根据这个式子只有比较小的\(f_y\)才能去更新\(f_x\),于是我们做一个类似于\(\rm Dijkstra\)的过程,每次从堆顶取出最小的\(f_y\)去更新即可

代码

#include<bits/stdc++.h>
#define re register
#define mp std::make_pair
inline int read() {
    char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
const int maxn=3e5+5;
typedef std::pair<double,int> pii;
std::priority_queue<pii,std::vector<pii>,std::greater<pii> > q;
struct E{int v,nxt;}e[maxn<<1];
int n,num,m;
double dis[maxn],s[maxn],p[maxn];
int du[maxn],head[maxn],vis[maxn];
inline void add(int x,int y) {e[++num].v=y;e[num].nxt=head[x];head[x]=num;}
int main() {
    n=read(),m=read();
    for(re int x,y,i=1;i<=m;i++)    
        x=read(),y=read(),du[x]++,du[y]++,add(x,y),add(y,x);
    dis[n]=0,q.push(mp(dis[n],n));
    while(!q.empty()) {
        int k=q.top().second;q.pop();
        if(vis[k]) continue;vis[k]=1;
        for(re int i=head[k];i;i=e[i].nxt) {
            if(vis[e[i].v]) continue;
            p[e[i].v]+=1;s[e[i].v]+=dis[k];
            dis[e[i].v]=(du[e[i].v]+s[e[i].v])/p[e[i].v];
            q.push(mp(dis[e[i].v],e[i].v));
        }
    }
    printf("%.10lf\n",dis[1]);
    return 0;
}

原文地址:https://www.cnblogs.com/asuldb/p/11567552.html