【图论】用线段树写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 输出当前最小值,若不存 ...
随机推荐
- If-Else 太多,如何优化!!!
完全不必要的 Else 块 public void consumer(int product) { if (product > 1) { // do something } else { // ...
- Redis泛泛而谈(详细2W字)
本文适合于刚接触redis的,文章内容比较基础,大佬请绕道. 一.NoSQL入门和概述 Ⅰ-入门概述 1.为什么用NoSQL 1)单机MySQL的美好年代 在90年代,一个网站的访问量一般都不大,用单 ...
- Ribbon导航
简介 最近都在弄微服务的东西,现在来记录下收获.我从一知半解到现在能从0搭建使用最大的感触有两点 1.微服务各大组件的版本很多,网上很多博客内容不一定适合你的版本,很多时候苦苦琢磨都是无用功 2.网上 ...
- [java] IDEA
快捷键 shift+shift:搜索 ctrl+d:复制行 ctrl+x:删除行 ctrl+p:查看方法参数 ctrl+o:查看类方法 ctrl+h:查看类结构 ctrl+i:实现接口方法 ctrl+ ...
- CentOS 8.2远程连接vncserver升级后1.10.1无法启动解决记录
CentOS 8.2远程连接vncserver升级后1.10.1无法启动解决记录 问题起源:手贱yum upgrade,重启服务器后无法使用vnc viewer远程连接 查看状态 # system ...
- elasticksearch分词,导致kibana的url出现问题
在Kibana的展示页面中,我们点击Table的左侧栏,发现Elasticsearch中的数据在展示中是正确的数据,比如:agent中www.baidu.com/test,该界面中会正确的显示为www ...
- mysql基础之mariadb概念
一.数据库介绍 什么是数据库(Database)? 简单的说,数据库就是一个存放数据的仓库,这个仓库是按照一定的数据结构(数据结构是指数据的组织形式或数据之间的联系)来组织,存储的,我们可以通过数据库 ...
- 2020-1-19 2.港股打新、REITs和分拆
1.港股打新介绍 港股打新升级版 财属目由尽握手中 港股中签率较高 A股提高中签率 港股提高中签之后的收益率 有可能破发 2.第一版港股打新 港股打新第一版 ■第一种策略:只选择低于1.5港币的 配售 ...
- go输出九九乘法表和金字塔
用go语言实现输出九九乘法表和金字塔: 1.输出九九乘法表: 代码示例: package main import ( "fmt" "time" ) //实现99 ...
- Python中PyQuery库的使用
pyquery库是jQuery的Python实现,可以用于解析HTML网页内容,我个人写过的一些抓取网页数据的脚本就是用它来解析html获取数据的. 它的官方文档地址是:http://packages ...