题目


分析(\(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. 【Azure 应用服务】记一次Azure Spring Cloud 的部署错误 (az spring-cloud app deploy -g dev -s testdemo -n demo -p ./hellospring-0.0.1-SNAPSHOT.jar --->>> Failed to wait for deployment instances to be ready)

    问题描述 使用Azure Spring Cloud服务,在部署时候失败,收到错误消息为: c:\project\hellospring>az spring-cloud app deploy -g ...

  2. RocketMQ—RocketMQ集成SpringBoot

    RocketMQ-RocketMQ集成SpringBoot 新建生产者的boot项目和消费者的boot项目,pom文件重点如下: <dependencies> <dependency ...

  3. JS2-DOM

    API和Web API API 应用程序编程接口,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,且又无需访问源码,或理解内部工作机制的细节 API是给程序员提供的一种工具,以便能 ...

  4. 面试官:线程调用2次start会怎样?我支支吾吾没答上来

    写在开头 在写完上一篇文章<Java面试必考题之线程的生命周期,结合源码,透彻讲解!>后,本以为这个小知识点就总结完了. 但刚刚吃晚饭时,突然想到了多年前自己面试时的亲身经历,决定再回来补 ...

  5. [VueJsDev] 日志 - BBTime-LOG

    [VueJsDev] 目录列表 https://www.cnblogs.com/pengchenggang/p/17037320.html BBTime-LOG ::: details 目录 目录 B ...

  6. .NET数据库ORM框架SqlSugar使用笔记

    官方介绍 以下介绍来自SqlSugar官网: 高性能 ,不夸张的说,去掉Sql在数据库执行的时间,SqlSugar是EF数倍性能,另外在批量操作和一对多查询上也有不错的SQL优化 高扩展性 ,支持自定 ...

  7. linux控制显示器的亮度

    我使用的manjaro yay -S redshift -b 白天:晚上 要应用的屏幕亮度(在 0.1 和 1.0 之间) -c 文件 从指定的配置文件加载设置 -g R:G:B 要应用的其他伽马校正 ...

  8. [SCOI 2009] 迷路 (矩阵快速幂)

    [SCOI 2009]迷路 传送门 问题描述 Windy 在有向图中迷路了. 该有向图有 \({N}\) 个节点,Windy 从节点 \({1}\) 出发,他必须恰好在 \({T}\) 时刻到达节点 ...

  9. 关于api的表优化及代码优化小结

    提示:近期有空整理下mysql设计注意点吧 文章目录 一.表设计方面 二.代码设计方面 总结 一.表设计方面 建表要求三范式 5个必须字段is_del,create_time(CURRENT_TIME ...

  10. Spring之事务传播属性

    在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量. 在使用Spring时,大部分会用到他的声明式事务,简单的在配置文件中进行一些规则 ...