1. 程式人生 > >和Leo一起做愛數學的好孩子之CERC2017 Gambling Guide

和Leo一起做愛數學的好孩子之CERC2017 Gambling Guide

一個在鄰國的鐵路系統是由nn個城市(編號從11到nn),和mm條連線兩個不同城市的雙向鐵路組成的。鐵路票只能在安裝在每個城市的自動售票機購買。不幸的是,黑客們已經篡改了這些售票機,現在它們有下面的規則: 當aa市的售票機有一個硬幣投入時,機器會發一張從aa市到隨機一個鄰市的單程票。更精確地來說,目的地城市是被統一的、隨機的從所有由出發城市為起點的鐵路的終點中選取的。

一個研究電腦科學的學生需要從城市11(她生活在那裡)到城市nn(那裡正舉行一個程式設計比賽)。她知道機器是怎麼工作的(但當然她不能預測隨機的目的地)並且有一份鐵路系統的地圖。在每一個城市,當她買了一張票時,她可以選擇立即使用它後到達目的地,或者是丟掉它並買一張新票。她可以無限制的購買的票。當她一到達n城市,旅行就會結束。

在做了一些計算之後,她制定了一個擁有以下的目標的旅行計劃:

  • 旅行最終到達終點的概率為1
  • 預期花在旅行上的硬幣越少越好

找到這個預期的她要花在旅途上的硬幣數

額。怎麼讓期望概率為1:

這個我最先想的是:以n為起點跑一次最短路,每次轉移更近的節點。

但這並不完全正確

因為:這個最短路距離並不是實際的花費

所以應當轉移:期望距離

這個時候需要用Dijkstra轉移

F_{i}為期望步數他按照剛剛的理論可以跟新所有大於他的狀態

答案為F_{i}=\(\frac{ \sum_{son}(F_{son}*(F[son]<F[i])+1)}{Du[i]})

用堆貪心轉移就好了

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
inline void read(int &x){
    x=0;
    char ch=getchar();
    int f=1;
    while(ch<'0'||ch>'9'){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    x*=f;
}
struct Front_star{
    int u,v,nxt;
}e[N<<1];
int cnt=0;
int first[N];
void add(int u,int v){
    ++cnt;
    e[cnt].u=u;
    e[cnt].v=v;
    e[cnt].nxt=first[u];
    first[u]=cnt;
}
struct Node{
    double len;
    int u;
};
priority_queue<Node> Q;
bool operator < (Node A,Node B){
    return A.len>B.len;
}
double F[N];
double s[N];
int d[N];
int vis[N];
int c[N];
int n,m;
int main(){
//	freopen("test.in","r",stdin);
    read(n);
    read(m);
    for(int i=1;i<=m;++i){
        int u,v;
        read(u);
        read(v);
        add(u,v);
        add(v,u);
        d[u]++;
        d[v]++;
    }
    Q.push((Node){0,n});
    while(!Q.empty()){
        Node Now=Q.top();
        Q.pop();
        int u=Now.u;
        if(vis[u])continue;
        vis[u]=1;
        for(int i=first[u];i;i=e[i].nxt){
            int v=e[i].v;
            if(vis[v])continue;
            c[v]++;
            s[v]+=F[u];
            F[v]=(s[v]+d[v])/((double)c[v]);
            Q.push((Node){F[v],v});
        }
    }
    printf("%.8lf",F[1]);
}