【图论】用线段树写Dijikstra!!
速度是没有极限的。
众说周知,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!!的更多相关文章
- codeforces 876 D. Sorting the Coins(线段树(不用线段树写也行线段树写比较装逼))
题目链接:http://codeforces.com/contest/876/problem/D 题解:一道简单的类似模拟的题目.其实就是看右边连出来有多少连续不需要换的假设位置为pos只要找pos- ...
- 2018.11.01 NOIP训练 图论(线段树+倍增+dfs序)
传送门 一道挺妙的题. 对于询问点(u,v),如右图所示,我们可以发现存在一个点m在u->v的路径中,m子树的点到u是最近的,m子树外到v是最近的.其中dis(u,m)=(dis(u,v)-1) ...
- 用线段树写Dijkstar
如题 noip前就想用线段树优化Dijkstar 写那啥,感觉挺好玩的 写了个线段树优化的Dijkstar #include<cstdio> #include<cstring> ...
- 【BZOJ-4653】区间 线段树 + 排序 + 离散化
4653: [Noi2016]区间 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 107 Solved: 70[Submit][Status][Di ...
- Mango DS Traning #49 ---线段树3 解题手记
Training address: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=38994#overview B.Xenia and B ...
- 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 ...
- LightOJ 1085(树状数组+离散化+DP,线段树)
All Possible Increasing Subsequences Time Limit:3000MS Memory Limit:65536KB 64bit IO Format: ...
- Vijos P1103 校门外的树【线段树,模拟】
校门外的树 描述 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置:数轴上的每个整数点,即0,1,2,……, ...
- BZOJ_3685_普通van Emde Boas树_权值线段树
BZOJ_3685_普通van Emde Boas树_权值线段树 Description 设计数据结构支持: 1 x 若x不存在,插入x 2 x 若x存在,删除x 3 输出当前最小值,若不存 ...
随机推荐
- ConcurrentHashMap源码解读二
接下来就讲解put里面的三个方法,分别是 1.数组初始化方法initTable() 2.线程协助扩容方法helpTransfer() 3.计数方法addCount() 首先是数组初始化,再将源码之前, ...
- 通过Dapr实现一个简单的基于.net的微服务电商系统(十一)——一步一步教你如何撸Dapr之自动扩/缩容
上一篇我们讲到了dapr提供的bindings,通过绑定可以让我们的程序轻装上阵,在极端情况下几乎不需要集成任何sdk,仅需要通过httpclient+text.json即可完成对外部组件的调用,这样 ...
- java并发编程:深入了解synchronized
简介 synchronized是Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码.同时它还保证了共享变量的内存可见性. ...
- 7. IDEA概述和安装
1.1IDEA概述 IDEA全称InteliJ IDEA,是用于Java语言开发的继承环境,它是业界公认的目前用于Java程序开发的最好工具 集成环境:把代码编写,编译,执行,调试等多种功能综合到一起 ...
- Markdown使用概述
Markdown使用概述 序言 作为一名编程学习的爱好者和初学者,由于学习编程的过程中总是存在遗忘以及很难动手写起来的问题,所以在看了许多关于编程学习方法的文章之后,选择使用typora作为我的笔记工 ...
- Zabbix 监控介绍
Zabbix 监控介绍 1.Zabbix监控架构 2.Zabbix 优点 开源无软件成本投入 Server对设备性能要求低 支持设备多,自带多种监控模板 支持分布式集中管理,有自动发现功能,可以实现自 ...
- nginx的四层转发功能
架构图 配置过程 配置web服务器 # 1.配置web01,更改配置文件 [root@web01 /etc/nginx/conf.d]# vi test1.conf server { listen 8 ...
- STM32标准外设库中USE_STDPERIPH_DRIVER, STM32F10X_MD的含义
在项目中使用stm32标准外设库(STM32F10x Standard Peripherals Library)的时候,我们会在项目的选项中预定义两个宏定义:USE_STDPERIPH_DRIVER, ...
- java并发编程工具类JUC第一篇:BlockingQueue阻塞队列
Java BlockingQueue接口java.util.concurrent.BlockingQueue表示一个可以存取元素,并且线程安全的队列.换句话说,当多线程同时从 JavaBlocking ...
- Python Xpath语法
Python Xpath语法 一.选取节点 常用的路劲表达式: 表达式 描述 实例 nodename 选取nodename节点的所有子节点 xpath('//div') 选取了div节点 ...