题目


分析(\(logk\)次Dijkstra)

首先为什么\(O(nklogn)\)的多次\(dijkstra\)为什么会TLE,

因为中间有许多的冗余状态,即使两点求出的路径是最短的,它也不一定是最优的,

怎样转换成单源最短路径问题,考虑建超级源点和超级汇点,要使两两之间的最短路径都能被统计,

那么考虑二进制拆分,将某一位的0或者1分成两部分跑最短路,这样保证关键点两两间最短路径不会遗漏

时间复杂度是\(O(nlognlogk)\)


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define rr register
using namespace std;
const int N=100011; typedef long long lll;
struct node{int y,w,next;}e[N*6];
pair<lll,int>heap[N]; lll ans,dis[N];
int as[N],n,m,K,kk,k,cnt,p[N],As[N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void Push(pair<lll,int>w){
heap[++cnt]=w;
rr int x=cnt;
while (x>1){
if (heap[x>>1]>heap[x])
swap(heap[x>>1],heap[x]),x>>=1;
else return;
}
}
inline void Pop(){
heap[1]=heap[cnt--];
rr int x=1;
while ((x<<1)<=cnt){
rr int y=x<<1;
if (y<cnt&&heap[y+1]<heap[y]) ++y;
if (heap[y]<heap[x]) swap(heap[y],heap[x]),x=y;
else return;
}
} inline lll Dijkstra(){
for (rr int i=1;i<n+3;++i) dis[i]=1e18;
dis[n+1]=0,heap[++cnt]=make_pair(0,n+1);
while (cnt){
rr int x=heap[1].second; rr lll t=heap[1].first;
Pop(); if (t!=dis[x]) continue;
for (rr int i=as[x];i;i=e[i].next)
if (dis[e[i].y]>dis[x]+e[i].w){
dis[e[i].y]=dis[x]+e[i].w;
Push(make_pair(dis[e[i].y],e[i].y));
}
}
return dis[n+2];
}
signed main(){
for (rr int T=iut();T;--T){
memset(as,0,sizeof(as)),ans=1e18;
n=iut(),m=iut(),K=iut(),k=1;
for (rr int i=1;i<=m;++i){
rr int x=iut(),y=iut(),w=iut();
e[++k]=(node){y,w,as[x]},as[x]=k;
}
for (rr int i=1;i<=K;++i) p[i]=iut();
memcpy(As,as,sizeof(as)),kk=k;
for (rr int i=0;(1<<i)<=K;++i){
memcpy(as,As,sizeof(As)),k=kk;
for (rr int j=1;j<=K;++j)
if ((j>>i)&1) e[++k]=(node){p[j],0,as[n+1]},as[n+1]=k;
else e[++k]=(node){n+2,0,as[p[j]]},as[p[j]]=k;
ans=min(ans,Dijkstra());
memcpy(as,As,sizeof(As)),k=kk;
for (rr int j=1;j<=K;++j)
if ((j>>i)&1) e[++k]=(node){n+2,0,as[p[j]]},as[p[j]]=k;
else e[++k]=(node){p[j],0,as[n+1]},as[n+1]=k;
ans=min(ans,Dijkstra());
}
printf("%lld\n",ans);
}
return 0;
}

分析(2次最短路)

虽然上述方法很常用,但是很容易被卡掉,

考虑枚举点或者边,使得两个关键点的最短路经过这个点或者这条边,

一个很常见的技巧就是标记最短路是由哪个关键点到的,

如果正反最短路的关键点不同,说明存在一条经过该点或该边的最短路

但是正确性不会证qwq


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define rr register
using namespace std;
const int N=100011; typedef long long lll;
struct node{int y,w,next;}e[N*10];
pair<lll,int>heap[N]; lll ans,dis[2][N];
int as[2][N],n,m,K,k,cnt,p[N],f[2][N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void Push(pair<lll,int>w){
heap[++cnt]=w;
rr int x=cnt;
while (x>1){
if (heap[x>>1]>heap[x])
swap(heap[x>>1],heap[x]),x>>=1;
else return;
}
}
inline void Pop(){
heap[1]=heap[cnt--];
rr int x=1;
while ((x<<1)<=cnt){
rr int y=x<<1;
if (y<cnt&&heap[y+1]<heap[y]) ++y;
if (heap[y]<heap[x]) swap(heap[y],heap[x]),x=y;
else return;
}
}
inline void Dijkstra(int z){
for (rr int i=1;i<=n;++i) dis[z][i]=1e18,f[z][i]=-1;
for (rr int i=1;i<=K;++i) f[z][p[i]]=p[i];
for (rr int i=1;i<=K;++i) Push(make_pair(dis[z][p[i]]=0,p[i]));
while (cnt){
rr int x=heap[1].second; rr lll t=heap[1].first;
Pop(); if (t!=dis[z][x]) continue;
for (rr int i=as[z][x];i;i=e[i].next)
if (dis[z][e[i].y]>dis[z][x]+e[i].w){
dis[z][e[i].y]=dis[z][x]+e[i].w,f[z][e[i].y]=f[z][x];
Push(make_pair(dis[z][e[i].y],e[i].y));
}
}
}
signed main(){
for (rr int T=iut();T;--T){
memset(as,0,sizeof(as)),ans=1e18;
n=iut(),m=iut(),K=iut(),k=1;
for (rr int i=1;i<=m;++i){
rr int x=iut(),y=iut(),w=iut();
e[++k]=(node){y,w,as[0][x]},as[0][x]=k;
e[++k]=(node){x,w,as[1][y]},as[1][y]=k;
}
for (rr int i=1;i<=K;++i) p[i]=iut();
Dijkstra(0),Dijkstra(1);
for (rr int i=1;i<=n;++i)
if (f[0][i]^f[1][i])
ans=min(ans,dis[0][i]+dis[1][i]);
for (rr int i=2;i<=k;i+=2)
if (f[0][e[i^1].y]^f[1][e[i].y])
ans=min(ans,dis[0][e[i^1].y]+e[i].w+dis[1][e[i].y]);
printf("%lld\n",ans);
}
return 0;
}

#Dijkstra,二进制拆位#洛谷 5304 [GXOI/GZOI2019]旅行者的更多相关文章

  1. 洛谷 P5304 [GXOI/GZOI2019]旅行者(最短路)

    洛谷:传送门 bzoj:传送门 参考资料: [1]:https://xht37.blog.luogu.org/p5304-gxoigzoi2019-lv-xing-zhe [2]:http://www ...

  2. [洛谷P5304][GXOI/GZOI2019]旅行者

    题目大意: 有一张 \(n(n\leqslant10^5)\) 个点 \(m(m\leqslant5\times10^5)\) 条边的有向有正权图,有$k(2\leqslant k\leqslant ...

  3. 洛谷.5300.[GXOI/GZOI2019]与或和(单调栈)

    LOJ BZOJ 洛谷 想了一个奇葩的单调栈,算的时候要在中间取\(\min\),感觉不靠谱不写了=-= 调了十分钟发现输出没取模=v= BZOJ好逗逼啊 题面连pdf都不挂了 哈哈哈哈 枚举每一位. ...

  4. [LOJ3087][GXOI/GZOI2019]旅行者——堆优化dijkstra

    题目链接: [GXOI/GZOI2019]旅行者 我们考虑每条边的贡献,对每个点求出能到达它的最近的感兴趣的城市(设为$f[i]$,最短距离设为$a[i]$)和它能到达的离它最近的感兴趣的城市(设为$ ...

  5. P5304 [GXOI/GZOI2019]旅行者

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

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

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

  7. 二进制拆位(贪心)【p2114】[NOI2014]起床困难综合症

    Description 21世纪,许多人得了一种奇怪的病:起床困难综合症,其临床表现为:起床难,起床后精神不佳.作为一名青春阳光好少年,atm一直坚持与起床困难综合症作斗争.通过研究相关文献,他找到了 ...

  8. BZOJ4888 [Tjoi2017]异或和 FFT或树状数组+二进制拆位

    题面 戳这里 简要题解 做法一 因为所有数的和才100w,所以我们可以直接求出所有区间和. 直接把前缀和存到一个权值数组,再倒着存一遍,大力卷积一波. 这样做在bzoj目前还过不了,但是luogu开O ...

  9. 4.26 ABC F I hate Matrix Construction 二进制拆位 构造 最大匹配

    LINK:I hate Matrix Construction 心情如题目名称. 主要说明一下构造的正确性. 准确来说这道题困扰我很久. 容易发现可以拆位构造. 这样题目中的条件也比较容易使用. 最后 ...

  10. 【Dijkstra堆优化】洛谷P2243电路维修

    题目背景 Elf 是来自Gliese 星球的少女,由于偶然的原因漂流到了地球上.在她无依无靠的时候,善良的运输队员Mark 和James 收留了她.Elf 很感谢Mark和James,可是一直也没能给 ...

随机推荐

  1. js结合canvas画任意多边形

    实现六边形 // html <canvas></canvas> // js const canvas = document.querySelector("canvas ...

  2. protobuf简单示例

    user.proto syntax = "proto3"; package demo; option go_package = "./pb"; //指定go_o ...

  3. SpringCloud组件:Feign之日志输出

    目录 Feign之日志输出 Feign日志输出说明 前期准备 构建项目 tairan-spring-cloud-feign-logger配置 源码位置 Feign之日志输出 在我们日常开发过程中,经常 ...

  4. 【Azure Developer】Github Action使用Azure/login@v1插件登录遇见错误的替代方案

    问题描述 在使用 Github Action  -  Azure/login@v1 的插件时候,登录中国区Azure遇见了问题. Login YAML 内容: - name: 'Login via A ...

  5. 【Azure Redis 缓存】Redis的监控方式? 是否有API接口调用来获取监控值

    问题描述 对于PaaS的Azure Cache for Redis,Azure中有哪些监控方式?是否能有api接口调用来获取监控值? 问题答案 1) 在Redis的门户中,使用Metrics查看Red ...

  6. 【Azure 环境】IntelliJ IDEA Community Edition 2021.2.3登陆Azure账号时,无法切换到中国区

    问题描述 在IntelliJ IDEA Community Edition 2021.2.3中开发Azure Function程序,最后准备部署到中国区 Azure Function中.如下,在Int ...

  7. 用图机器学习探索 A 股个股相关性变化

    在本系列的前文 [1,2]中,我们介绍了如何使用 Python 语言图分析库 NetworkX [3] + Nebula Graph [4] 来进行<权力的游戏>中人物关系图谱分析. 在本 ...

  8. 小程序开发:接入腾讯云的人像动漫化api接口

    接口如下: 图片的传参方式有两种,一种是传图片的base64,一种是图片url: 我打算免费版使用base64,如果付费用户支持永久存储历史的图片记录(图片存储到腾讯云对象存储中). 前端框架我用的u ...

  9. (完美解决)chatGPT登陆正常却无法发送消息

    这几天要写关于项目的文字性材料,登陆上chatgpt,结果发现登陆正常,各方面都正常,但是点击发送消息就会不停转圈圈,无法发送出去,然后联想到之前看到朋友圈有人说chatGPT崩了,就没多在意,结果今 ...

  10. 巧用SQL语句中的OR查询完成业务新需求-2022新项目

    一.业务场景 目前参与开发的项目,之前的一个已上线的版本中有一类查询是根据两张表进行LEFT JOIN查询用来取数据, 主表中有一个字段field用来区分不同的数据类型比如说A/B/C.前面的版本中只 ...