一个在邻国的铁路系统是由nn个城市(编号从11到nn),和mm条连接两个不同城市的双向铁路组成的。铁路票只能在安装在每个城市的自动售票机购买。不幸的是,黑客们已经篡改了这些售票机,现在它们有下面的规则: 当aa市的售票机有一个硬币投入时,机器会发一张从aa市到随机一个邻市的单程票。更精确地来说,目的地城市是被统一的、随机的从所有由出发城市为起点的铁路的终点中选取的。
一个研究计算机科学的学生需要从城市11(她生活在那里)到城市nn(那里正举行一个编程比赛)。她知道机器是怎么工作的(但当然她不能预测随机的目的地)并且有一份铁路系统的地图。在每一个城市,当她买了一张票时,她可以选择立即使用它后到达目的地,或者是丢掉它并买一张新票。她可以无限制的购买的票。当她一到达n城市,旅行就会结束。
在做了一些计算之后,她制定了一个拥有以下的目标的旅行计划:
- 旅行最终到达终点的概率为1
- 预期花在旅行上的硬币越少越好
找到这个预期的她要花在旅途上的硬币数
额。怎么让期望概率为1:
这个我最先想的是:以n为起点跑一次最短路,每次转移更近的节点。
但这并不完全正确
因为:这个最短路距离并不是实际的花费
所以应当转移:期望距离
这个时候需要用Dijkstra转移
设为期望步数他按照刚刚的理论可以跟新所有大于他的状态
答案为
用堆贪心转移就好了
#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]);
}