题目链接:

[GXOI/GZOI2019]旅行者

我们考虑每条边的贡献,对每个点求出能到达它的最近的感兴趣的城市(设为$f[i]$,最短距离设为$a[i]$)和它能到达的离它最近的感兴趣的城市(设为$g[i]$,最短距离设为$b[i]$)。

那么每条边$(u,v,w)$的贡献就是$a[u]+w+b[v]$,用这个值去更新答案即可(这个值代表$f[u]$到$g[v]$的最短路长度)。

但要注意一条边能更新答案需要满足$f[u]\neq g[v]$,因为要保证起点和终点不同。

手画一下就可以知道最短路径上的边至少有一条会更新答案,即不可能发生最短路径上每条边的$f[u]=g[v]$。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define pr pair<ll,int>
using namespace std;
int tot;
int head[100010];
int to[600010];
int nex[600010];
int val[600010];
ll ans;
int tim;
int n,m,k;
int u[500010];
int v[500010];
int w[500010];
ll d[100010];
ll c[100010];
int f[100010];
int g[100010];
int a[100010];
int vis[100010];
priority_queue< pr,vector<pr>,greater<pr> >q;
void init()
{
memset(head,0,sizeof(head));
memset(val,0,sizeof(val));
memset(nex,0,sizeof(nex));
memset(to,0,sizeof(to));
memset(f,0,sizeof(f));
memset(c,0,sizeof(c));
memset(g,0,sizeof(g));
memset(d,0,sizeof(d));
memset(v,0,sizeof(v));
memset(w,0,sizeof(w));
memset(u,0,sizeof(u));
tot=0;
}
void add(int x,int y,int z)
{
nex[++tot]=head[x];
head[x]=tot;
to[tot]=y;
val[tot]=z;
}
void dijkstra(int opt)
{
tot=0;
memset(vis,0,sizeof(vis));
memset(head,0,sizeof(head));
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++)
{
d[i]=1ll<<60;
}
for(int i=1;i<=k;i++)
{
d[a[i]]=0;
f[a[i]]=a[i];
q.push(make_pair(d[a[i]],a[i]));
}
for(int i=1;i<=m;i++)
{
if(!opt)
{
add(u[i],v[i],w[i]);
}
else
{
add(v[i],u[i],w[i]);
}
}
while(!q.empty())
{
int now=q.top().second;
q.pop();
if(vis[now])
{
continue;
}
vis[now]=1;
for(int i=head[now];i;i=nex[i])
{
if(d[to[i]]>d[now]+val[i])
{
d[to[i]]=d[now]+val[i];
f[to[i]]=f[now];
q.push(make_pair(d[to[i]],to[i]));
}
}
}
}
void solve()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&u[i],&v[i],&w[i]);
}
for(int i=1;i<=k;i++)
{
scanf("%d",&a[i]);
}
dijkstra(0);
for(int i=1;i<=n;i++)
{
c[i]=d[i],g[i]=f[i];
}
dijkstra(1);
ll ans=1ll<<60;
for(int i=1;i<=m;i++)
{
if(g[u[i]]&&f[v[i]]&&g[u[i]]!=f[v[i]])
{
ans=min(ans,c[u[i]]+d[v[i]]+w[i]);
}
}
printf("%lld\n",ans);
}
int main()
{
scanf("%d",&tim);
while(tim--)
{
init();
solve();
}
}

[LOJ3087][GXOI/GZOI2019]旅行者——堆优化dijkstra的更多相关文章

  1. P5304 [GXOI/GZOI2019]旅行者

    题目地址:P5304 [GXOI/GZOI2019]旅行者 这里是官方题解 一个图 \(n\) 点 \(m\) 条边,里面有 \(k\) 个特殊点,问这 \(k\) 个点之间两两最短路的最小值是多少? ...

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

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

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

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

  4. 【BZOJ5506】[GXOI/GZOI2019]旅行者(最短路)

    [BZOJ5506][GXOI/GZOI2019]旅行者(最短路) 题面 BZOJ 洛谷 题解 正着做一遍\(dij\)求出最短路径以及从谁转移过来的,反过来做一遍,如果两个点不由同一个点转移过来就更 ...

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

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

  6. 配对堆优化Dijkstra算法小记

    关于配对堆的一些小姿势: 1.配对堆是一颗多叉树. 2.包含优先队列的所有功能,可用于优化Dijkstra算法. 3.属于可并堆,因此对于集合合并维护最值的问题很实用. 4.速度快于一般的堆结构(左偏 ...

  7. POJ 3635 - Full Tank? - [最短路变形][手写二叉堆优化Dijkstra][配对堆优化Dijkstra]

    题目链接:http://poj.org/problem?id=3635 题意题解等均参考:POJ 3635 - Full Tank? - [最短路变形][优先队列优化Dijkstra]. 一些口胡: ...

  8. 【堆优化Dijkstra+字典序最短路方案】HDU1385-Minimum Transport Cost

    [题目大意] 给出邻接矩阵以及到达各个点需要付出的代价(起点和终点没有代价),求出从给定起点到终点的最短路,并输出字典序最小的方案. [思路] 在堆优化Dijkstra中,用pre记录前驱.如果新方案 ...

  9. 【bzoj5197】[CERC2017]Gambling Guide 期望dp+堆优化Dijkstra

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

随机推荐

  1. 第一册:lesson 119.

    原文: A true story. question:Who called out to the thieves in the dark? Do you like stories? I want to ...

  2. 【网摘】C#.NET 在 MVC 中动态绑定下拉菜单的方法

    1. 已知下拉菜单列表项: 在 Controller 控制器类中输入已下代码  1 public class DemoController : Controller 2 { 3     public  ...

  3. java类的继承(基础)

    ---恢复内容开始--- 这篇随笔和大家讲讲java中类的继承是什么?希望对你们有所帮助. 目录 一.java继承是什么? 二.为什么使用java继承 三.java继承的实现 1.1  java继承的 ...

  4. .net基础系列

    这里汇总了.net基础的相关文章,方便查阅! .net基础 委托(1)认识委托 委托(2).net 1.x中的委托 委托(3).net 2.0中的委托 委托(4).net 3.5中的委托 委托(5)委 ...

  5. 随笔:关于去年的WordPress建站的回忆

    2018-02-26    建站 2018-02-28    选择主题Clearision 2018-03-01    学习插入视频.修改主题 <iframe src="//playe ...

  6. SQL SERVER 2012 AlwaysOn - 维护篇 03

    搭建 AlwaysOn 是件非常繁琐的工作,需要从两方面考虑,操作系统层面和数据库层面,AlwaysOn 非常依赖于操作系统,域控,群集,节点等概念: DBA 不但要熟悉数据库也要熟悉操作系统的一些概 ...

  7. C# Base64方式的编码与解码

    编码与解码方法: ///编码 public static string EncodeBase64(string code_type, string code) { string encode = &q ...

  8. 浅析C#中new、override、virtual关键字的区别

    Virtual : virtual 关键字用于修饰方法.属性.索引器或事件声明,并使它们可以在派生类中被重写. 默认情况下,方法是非虚拟的.不能重写非虚方法. virtual 修饰符不能与 stati ...

  9. jquery中Json操作

    在开发中,我们有可能拿到的不是全的json,而是一部分json格式的数据,这个时候我们需要将其强转为json对象 第一种方法:使用jquery中的$.parseJSON(),但是它对json数据格式的 ...

  10. 关键字-this

    1.当成员变量和局部变量重名时,在方法中使用this时,this指向的是该方法所在类的成员变量. package gc.test.java.cs1; public class User{ public ...