题目描述

给定一张n个点,m条双向边的无向图。
你要从1号点走到n号点。当你位于x点时,你需要花1元钱,等概率随机地买到与x相邻的一个点的票,只有通过票才能走到其它点。
每当完成一次交易时,你可以选择直接使用那张票,也可以选择扔掉那张票然后再花1元钱随机买另一张票。注意你可以无限次扔票。
请使用最佳的策略,使得期望花的钱数最少。

输入

第一行包含两个正整数n,m(1<=n,m<=300000),表示点数和边数。
接下来m行,每行两个正整数u,v(1<=u,v<=n),表示一条双向边。
输入数据保证无重边、无自环,且1号点一定可以走到n号点。

输出

输出一行一个实数,即最少的期望花费,当绝对或者相对误差不超过10^{-6}时视为正确。

样例输入

5 8
1 2
1 3
1 4
2 3
2 4
3 5
5 4
2 5

样例输出

4.1111111111


题解

期望dp+堆优化Dijkstra

设 $f[i]$ 表示 $i$ 到终点的期望步数,那么有:$f[n]=0\ ,\ f[x]=\frac{\sum\limits_{(x,y)}\text{min}(f[x],f[y])+1}{d[x]}$ ,其中 $d[x]$ 表示 $x$ 的度数。

套路:对于这种 “初始只有一个点的dp值确定、其它点的dp值与其相邻的点有关” 的图上dp,考虑使用类似最短路的方式转移。

初始的时候除了 $n$ 以外,每个点的 $\text{min}(f[x],f[y])$ 都取 $f[x]$ ,dp值为 $+\infty$ 。

然后从 $n$ 号点开始最短路转移:对于当前的点 $i$ ,如果某个相邻的 $j$ 有 $f[j]>f[i]$ ,则对于 $f[j]$ 的计算来说,$\text{min}(f[j],f[i])$ 取 $f[i]$ 更优。此时更新 $j$ 的dp值,并将 $j$ 加入到待用于更新其它点的集合中。

注意到:如果使用 $f[i]$ 将 $f[j]$ 更新为 $f'[j]$ ,那么显然有 $f[i]\le f'[j]\le f[j]$ (等号在 $f[i]=f[j]$ 时取到),满足堆优化Dijkstra的贪心策略(当前最小的一定不会再被更新到更小),因此可以使用dp值小根堆来维护待用于更新其它点的集合,使用类似堆优化Dijkstra的方式转移即可。

最终的答案就是 $f[1]$ 。

时间复杂度 $O(m\log n)$

#include <queue>
#include <cstdio>
#include <algorithm>
#define N 300010
using namespace std;
typedef pair<double , int> pr;
priority_queue<pr> q;
double s[N] , f[N];
int head[N] , to[N << 1] , next[N << 1] , cnt , vis[N] , d[N] , c[N];
inline void add(int x , int y)
{
to[++cnt] = y , next[cnt] = head[x] , head[x] = cnt;
}
int main()
{
int n , m , i , x , y;
scanf("%d%d" , &n , &m);
for(i = 1 ; i <= m ; i ++ ) scanf("%d%d" , &x , &y) , add(x , y) , add(y , x) , d[x] ++ , d[y] ++ ;
q.push(pr(0 , n));
while(!q.empty())
{
x = q.top().second , q.pop();
if(vis[x]) continue;
vis[x] = 1;
for(i = head[x] ; i ; i = next[i])
if(!vis[to[i]])
c[to[i]] ++ , s[to[i]] += f[x] , f[to[i]] = (s[to[i]] + d[to[i]]) / c[to[i]] , q.push(pr(-f[to[i]] , to[i]));
}
printf("%lf\n" , f[1]);
return 0;
}

【bzoj5197】[CERC2017]Gambling Guide 期望dp+堆优化Dijkstra的更多相关文章

  1. [BZOJ5197] [CERC2017]Gambling Guide

    [BZOJ5197] [CERC2017]Gambling Guide 题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=5197 Solut ...

  2. 【bzoj1097】[POI2007]旅游景点atr 状压dp+堆优化Dijkstra

    题目描述 FGD想从成都去上海旅游.在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情.经过这些城市的顺序不是完全随意的,比如说FGD不希望在刚吃过一顿大餐之后立刻去下一个 ...

  3. Luogu4745/Gym101620G CERC2017 Gambling Guide 期望、DP、最短路

    传送门--Luogu 传送门--Vjudge 设\(f_x\)为从\(x\)走到\(N\)的期望步数 如果没有可以不动的限制,就是隔壁HNOI2013 游走 如果有可以不动的限制,那么\(f_x = ...

  4. BZOJ5197:[CERC2017]Gambling Guide(最短路,期望DP)

    Description 给定一张n个点,m条双向边的无向图. 你要从1号点走到n号点.当你位于x点时,你需要花1元钱,等概率随机地买到与x相邻的一个点的票,只有通过票才能走到其它点. 每当完成一次交易 ...

  5. 【BZOJ5197】Gambling Guide (最短路,期望)

    [BZOJ5197]Gambling Guide (最短路,期望) 题面 BZOJ权限题 洛谷 题解 假设我们求出了每个点的期望,那么对于一个点,只有向期望更小的点移动的时候才会更新答案. 即转移是: ...

  6. 【bzoj4016】[FJOI2014]最短路径树问题 堆优化Dijkstra+DFS树+树的点分治

    题目描述 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径( ...

  7. BZOJ 3040 最短路 (堆优化dijkstra)

    这题不是裸的最短路么?但是一看数据范围就傻了.点数10^6,边数10^7.这个spfa就别想了(本来spfa就是相当不靠谱的玩意),看来是要用堆优化dijkstra了.但是,平时写dijkstra时为 ...

  8. UVA - 11374 - Airport Express(堆优化Dijkstra)

    Problem    UVA - 11374 - Airport Express Time Limit: 1000 mSec Problem Description In a small city c ...

  9. BZOJ5415[Noi2018]归程——kruskal重构树+倍增+堆优化dijkstra

    题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 n 个节点.m 条边的无向连通图(节点的编号从 1 至 n).我们依次用 l,a 描述一条边的长度.海 ...

随机推荐

  1. 【BZOJ3110】【LG3332】[ZJOI2013]K大数查询

    [BZOJ3110][LG3332][ZJOI2013]K大数查询 题面 洛谷 BZOJ 题解 和普通的整体分治差不多 用线段树维护一下每个查询区间内大于每次二分的值\(mid\)的值即可 然后再按套 ...

  2. Android 学习1

    使用eclipse做为开发IDE, 导包快捷键 在显红的地方按shift+ctrl+o 另外自动补全使用alt+/

  3. 十、Django之Admin

    一.Django Admin 管理工具 Django 提供了基于 web 的管理工具. Django 自动管理工具是 django.contrib 的一部分.你可以在项目的 settings.py 中 ...

  4. JS Windows.document对象

    四中选择器:class ,id , name , 标签 通过选择器获取对象: ...................................ClassName('');  -- class选择 ...

  5. JVM知识(上)

    目录 什么是JVM? JVM的生命周期 JVM的体系结构 JVM的数据类型 java虚拟机被称为"虚拟",因为它是一个抽象的计算机定义的规范.要运行一个Java程序,需要一个抽象的 ...

  6. selenium +java 多个类公用driver问题

    问题点:太久没有写selenium代码,居然把driver公用的问题忘记了,即:每写一个测试类,执行过程中都会新建一个窗口,这样应该说是非常不专业的. 大概想了一个方法,虽然看起来也不怎么专业,但感觉 ...

  7. CF刷题-Codeforces Round #481-D. Almost Arithmetic Progression

    题目链接:https://codeforces.com/contest/978/problem/D 题解: 题目的大意就是:这组序列能否组成等差数列?一旦构成等差数列,等差数列的公差必定确定,而且,对 ...

  8. Tree Traversals Again(根据前序,中序,确定后序顺序)

    题目的大意是:进行一系列的操作push,pop.来确定后序遍历的顺序 An inorder binary tree traversal can be implemented in a non-recu ...

  9. Oracle和MySQL在使用上的区别

    1.  Oracle是大型数据库而MySQL是中小型数据库,MySQL是开源的而Oracle的价格非常高. 2.  Oracle支持大并发,大访问量. 3.  安装所用的空间差别也是很大,MySQL安 ...

  10. openstack-r版(rocky)搭建基于centos7.4 的openstack swift对象存储服务 二

    openstack-r版(rocky)搭建基于centos7.4 的openstack swift对象存储服务 一 openstack-r版(rocky)搭建基于centos7.4 的openstac ...