速度是没有极限的。

众说周知,Dijikstra是一种最短路算法,复杂度为O(V^2+E)

朴素Dijikstra

void Dijikstra(int s){
memset(dis,inf,sizeof(dis));
dis[s]=0;
for(int i=1;i<=n;++i){
int maxs=inf,u=0;
for(int j=1;j<=n;++j)
if(!vis[j]&&dis[j]<maxs)
maxs=dis[j],u=j;
vis[u]=1;
for(int e=pre[u];e;e=nx[e]){
const int v=to[e];
if(dis[v]>dis[u]+w[e])
dis[v]=dis[u]+w[e];
}
}
}

其实对于稠密图它还是很棒了。 但我们不满足于此。

常见优化-heap优化

这里我们采用STL_priority_queue进行优化

typedef pair<int,int> p;
priority_queue<p,vector<p>,greater<p> > q;
void Dijikstra(int s){
memset(dis,inf,sizeof(dis));
dis[s]=0;
q.push(p(0,s));
while(!q.empty()){
const int u=q.top().second;
q.pop();
if(!vis[u]){
vis[u]=1;
for(int e=pre[u];e;e=nx[e]){
const int v=to[e];
if(!vis[v]&&dis[v]>dis[u]+w[e])
dis[v]=dis[u]+w[e],
q.push(p(dis[v],v));
}
}
}
}

这样的话复杂度就到了O((V+E)logV) 但是,常数大。 手写堆比较复杂,不现实。

奇怪的优化-线段树优化

这并不是自己发现的,但是网上资料少就记录一下吧。 我们回头看看朴素的Dijikstra以及priority_queue优化。 发现优化的主要思路就是减少了查询当前dis最小点的复杂度。 那么也很容易想到用线段树来维护dis的最小值吧。 这样问题就变成了 整体最小值与单点修改,很简单的线段树操作吧。

int tree[N<<2],leaf;
/*线段树存的是点的标号*/
int check(int i,int j){
return dis[i]<dis[j]?i:j;
}
void build(){
memset(dis,inf,sizeof(dis));
for(leaf=1;leaf<=n;leaf<<=1);--leaf;
for(int i=1;i<=n;++i) tree[leaf+i]=i;
}
/*修改 dis[x] 为 y*/
void change(int x,int y){
dis[x]=y,x+=leaf,x>>=1;
while(x) tree[x]=check(tree[x<<1],tree[x<<1|1]),x>>=1;
}
void Dijikstra(int s){
build();
dis[s]=0;
int u=s;
for(int i=1;i<=n;++i){
ans[u]=dis[u];
change(u,max_int); /*删除u*/
for(int e=pre[u];e;e=nx[e]){
const int v=to[e];
if(dis[v]>ans[u]+w[e])
change(v,ans[u]+w[e]);
}
u=tree[1];
}
}

这个比堆短吧。 而且非递归的线段树常数也很小呢。

测试&总结

以luogu的单源最短路模板题(稀疏图,无O2)作为测试。

  • 朴素的Dijikstra 2000+ms
  • Dijikstra+priority_queue 652ms
  • Dijikstra+线段树 192ms 然后加11了SLF和LLL的SPFA也很快,大概300ms

所以SPFA和Dijikstra+priority_queue是很实用的,但如果想卡排名的话可以试一试线段树啊

—来自xb神犇

【图论】用线段树写Dijikstra!!的更多相关文章

  1. codeforces 876 D. Sorting the Coins(线段树(不用线段树写也行线段树写比较装逼))

    题目链接:http://codeforces.com/contest/876/problem/D 题解:一道简单的类似模拟的题目.其实就是看右边连出来有多少连续不需要换的假设位置为pos只要找pos- ...

  2. 2018.11.01 NOIP训练 图论(线段树+倍增+dfs序)

    传送门 一道挺妙的题. 对于询问点(u,v),如右图所示,我们可以发现存在一个点m在u->v的路径中,m子树的点到u是最近的,m子树外到v是最近的.其中dis(u,m)=(dis(u,v)-1) ...

  3. 用线段树写Dijkstar

    如题 noip前就想用线段树优化Dijkstar 写那啥,感觉挺好玩的 写了个线段树优化的Dijkstar #include<cstdio> #include<cstring> ...

  4. 【BZOJ-4653】区间 线段树 + 排序 + 离散化

    4653: [Noi2016]区间 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 107  Solved: 70[Submit][Status][Di ...

  5. Mango DS Traning #49 ---线段树3 解题手记

    Training address: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=38994#overview B.Xenia and B ...

  6. Codeforces 446-C DZY Loves Fibonacci Numbers 同余 线段树 斐波那契数列

    C. DZY Loves Fibonacci Numbers time limit per test 4 seconds memory limit per test 256 megabytes inp ...

  7. LightOJ 1085(树状数组+离散化+DP,线段树)

    All Possible Increasing Subsequences Time Limit:3000MS     Memory Limit:65536KB     64bit IO Format: ...

  8. Vijos P1103 校门外的树【线段树,模拟】

    校门外的树 描述 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置:数轴上的每个整数点,即0,1,2,……, ...

  9. BZOJ_3685_普通van Emde Boas树_权值线段树

    BZOJ_3685_普通van Emde Boas树_权值线段树 Description 设计数据结构支持: 1 x  若x不存在,插入x 2 x  若x存在,删除x 3    输出当前最小值,若不存 ...

随机推荐

  1. Spring Cloud 升级之路 - 2020.0.x - 5. 理解 NamedContextFactory

    spring-cloud-commons 中参考了 spring-cloud-netflix 的设计,引入了 NamedContextFactory 机制,一般用于对于不同微服务的客户端模块使用不同的 ...

  2. [bug] VMvare 虚拟机磁盘空间耗尽

    问题 VMvare虚拟机文件默认创建在C盘,装大程序的时,空间用尽就会报错,此时补救的办法是把虚拟机文件复制到空间足够的盘,再重新打开 最好一开始就选再有足够空间的盘里创建虚拟机 参考 https:/ ...

  3. python-dict和list常用方法

    1 # *********-list-********* 2 # 创建一个list 3 list1 = [1, 2, '力气,', 'afd'] 4 print(type(list1)) 5 prin ...

  4. zabbix监控报警设置

    前提:已经安装好了zabbix server和zabbix agent 下面的方式不适合诸如用qq邮箱作为mail服务器,毫无疑问,zabbix支持自定义的邮件发送脚本,今天时间有限,改天在写!   ...

  5. Linux进阶之find命令、xshell速度慢的解决和Linux警告音的关闭

    一.Linux警告音关闭方法 1. 修改/etc/inputrc配置文件 set bell-style none    #取消该行注释 2. 修改~/.bashrc配置文件 在后面增加: setter ...

  6. git使用简单教程-(转自linux人)

    什么是Git Git是目前世界上最先进的分布式版本控制系统.最初由Linus Torvalds编写,用作Linux内核代码的管理.如果你是windows用户,看到这里你可能会担心"是不是只能 ...

  7. fprintf函数

    描述 C 库函数 int fprintf(FILE *stream, const char *format, ...) 发送格式化输出到流 stream 中. 声明 下面是 fprintf() 函数的 ...

  8. Day029 JDK8中新日期和时间API (二)

    # JDK8中新日期和时间API (二) Instant介绍 Instant:时间线上的一个瞬时点. 这可能被用来记录应用程序中的事件时间 戳. 在处理时间和日期的时候,我们通常会想到年,月,日,时, ...

  9. 安装篇--xshell评估过期解决方法

    打开XSHELL6(以自身版本为准,没有版本限制),弹出如上提示框,解决如下: 1.点击取消,不用卸载原来的,直接进入官网下载安装免费授权的https://www.netsarang.com/ 2.点 ...

  10. react-redux 源码浅析

    react-redux 版本号 7.2.3 react-redux 依赖的库: "dependencies": { "@babel/runtime": &quo ...