【Luogu P3371&P4779】【模板】单源最短路径(线段树优化Dijkstra)
线段树优化$\rm dijkstra$
线段树每个节点维护$[l,r]$中$dist$最小的点,删除则把该点$dist$赋值为$+\infty$,然后更新该点影响到的线段树上的其他节点即可。
可以得到“更新该节点影响到的线段树上的其他节点”部分的代码:
(线段树数组$\rm st[]$)
void pushup(int x) {
st[x] = dist[st[x << ]] < dist[st[x << | ]] ? st[x << ] : st[x << | ];
}
void updata(int x, int l, int r, int q) { //更新信息
if(l != r) {
int mid = (l + r) >> ;
if(q <= mid) updata(x << , l, mid, q);
else updata(x << | , mid + , r, q);
pushup(x);
}
}
然后$\rm dijkstra$代码如下:
//此处ans为最终数组
void dijkstra(int s) {
ans[s] = dist[s] = ;
build(, , n); //建树
while(dist[st[]] < inf) {
int v = st[]; vis[v] = ; //取出最小的
for(int i = head[v]; i != -; i = edges[i].nxt) if(!vis[edges[i].to]) { //更新相邻节点
dist[edges[i].to] = min(dist[edges[i].to], dist[v] + edges[i].val);//修改dist
updata(, , n, edges[i].to);//更新所影响的节点
}
ans[v] = dist[v]; dist[v] = inf;//记录答案,删除节点
updata(, , n, v); //更新所影响的节点
}
}
完整代码:
#include <bits/stdc++.h> using namespace std; const int MAXN = 1e5 + , inf = 0x3f3f3f3f; int st[MAXN << ], head[MAXN], dist[MAXN], ans[MAXN], n, m, cnt = ;
bool vis[MAXN]; struct edge {
int to, nxt, val;
} edges[MAXN << ]; void addedge(int from, int to, int val) {
edges[cnt].to = to, edges[cnt].val = val;
edges[cnt].nxt = head[from]; head[from] = cnt++;
} void pushup(int x) {
st[x] = dist[st[x << ]] < dist[st[x << | ]] ? st[x << ] : st[x << | ];
} void build(int x, int l, int r) {
if(l < r) {
int mid = (l + r) >> ;
build(x << , l, mid);
build(x << | , mid + , r);
pushup(x);
} else st[x] = l;
} void updata(int x, int l, int r, int q) {
if(l != r) {
int mid = (l + r) >> ;
if(q <= mid) updata(x << , l, mid, q);
else updata(x << | , mid + , r, q);
pushup(x);
}
} void dijkstra(int s) {
ans[s] = dist[s] = ;
build(, , n);
while(dist[st[]] < inf) {
int v = st[]; vis[v] = ;
for(int i = head[v]; i != -; i = edges[i].nxt) if(!vis[edges[i].to]) {
dist[edges[i].to] = min(dist[edges[i].to], dist[v] + edges[i].val);
updata(, , n, edges[i].to);
}
ans[v] = dist[v]; dist[v] = inf;
updata(, , n, v);
}
} int main() {
ios::sync_with_stdio(false);
memset(dist, 0x3f, sizeof(dist));
memset(head, 0xff, sizeof(head));
memset(ans, 0x3f, sizeof(ans));
int u, v, w, s;
cin >> n >> m >> s;
for(int i = ; i < m; i++) {
cin >> u >> v >> w;
addedge(u, v, w);
}
dijkstra(s);
for(int i = ; i <= n; i++) cout << ans[i] << " ";
cout << endl;
return ;
}
【Luogu P3371&P4779】【模板】单源最短路径(线段树优化Dijkstra)的更多相关文章
- 【洛谷 p3371】模板-单源最短路径(图论)
题目:给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 解法:spfa算法. 1 #include<cstdio> 2 #include<cstdlib> 3 #in ...
- luogu P3834 【模板】可持久化线段树 1(主席树) 查询区间 [l, r] 内的第 k 小/大值
————————————————版权声明:本文为CSDN博主「ModestCoder_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明.原文链接:https:// ...
- 【BZOJ】BZOJ3040 最短路 线段树优化Dijkstra
题目描述 N个点,M条边的有向图,求点1到点N的最短路(保证存在). 1<=N<=1000000,1<=M<=10000000 输入格式 第一行两个整数N.M,表示点数和边数. ...
- [CF787D]遗产(Legacy)-线段树-优化Dijkstra(内含数据生成器)
Problem 遗产 题目大意 给出一个带权有向图,有三种操作: 1.u->v添加一条权值为w的边 2.区间[l,r]->v添加权值为w的边 3.v->区间[l,r]添加权值为w的边 ...
- [模板]单源最短路径(Dijkstra)
如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 主要还是再打一遍最短路,这种算法我用的不多... #include<bits/stdc++.h> using namesp ...
- luogu P3834 【模板】可持久化线段树 1(主席树)
题解真的是越写越懒 // luogu-judger-enable-o2 #include<cstdio> #include<algorithm> using std::sort ...
- luogu 3834 【模板】可持久化线段树 1(主席树)
我这种菜鸡还是%一下棒神比较好 #include<iostream> #include<cstdio> #include<cmath> #include<cs ...
- 堆优化/zkw线段树优化 dijkstra
#include <bits/stdc++.h> using namespace std; const int MAXN = 100005; const int MAXM = 200005 ...
- Dijkstra求解单源最短路径
Dijkstra(迪杰斯特拉)单源最短路径算法 Dijkstra思想 Dijkstra是一种求单源最短路径的算法. Dijkstra仅仅适用于非负权图,但是时间复杂度十分优秀. Dijkstra算法主 ...
随机推荐
- 【迷你微信】基于MINA、Hibernate、Spring、Protobuf的即时聊天系统:6.技术简介之Protobuf
欢迎阅读我的开源项目<迷你微信>服务器与<迷你微信>客户端 protocolbuffer(以下简称Protobuf)是google 的一种数据交换的格式,它独立于语言,独立于平 ...
- SQL Server(第二章) 字符串函数、日期时间函数、转换函数
--1.CONCAT 函数:字符串连接(支持sql server2012 SQL规则 如果与NULL连接返回NILL) SELECT empid,CONCAT(firstname,lastname) ...
- 在SQL中查看文件组中有哪些表
SELECT o.[name], o.[type], i.[name], i.[index_id], f.[name] FROM sys.indexes i INNER JOIN sys.filegr ...
- C#环形缓冲区(队列)完全实现
公司项目中经常设计到串口通信,TCP通信,而且大多都是实时的大数据的传输,然后大家都知道协议通讯肯定涉及到什么,封包.拆包.粘包.校验--什么鬼的概念一大堆,说简单点儿就是要一个高效率可复用的缓存区. ...
- UOJ#210. 【UER #6】寻找罪犯 2-sat
#210. [UER #6]寻找罪犯 链接:http://uoj.ac/problem/210 想法:2-sat模型.每个人拆点,分别表示为犯人.非犯人.每个句供词拆点,分别表示真话.假话.供词与对应 ...
- ES6中set和map的区别
Set ES6提供了新的数据结构Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. Set函数可以接受一个数组(或类似数组的对象)作为参数,用来初始化. // 例一 var set = ne ...
- PHP:implode(),emplode() 字符串数组,数组字符串转换函数
1.implode()-Join array elements with a string(把数组元素组合为一个字符串.) string implode([string $separator,] ar ...
- [VC]线程
是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共 享进程所拥有的全部资源.一个线程可以创建和撤消另一个线 ...
- Android(java)学习笔记85:使用SQLite的基本流程
- wepy框架构建小程序(1)
wepy框架构建小程序(1) 基本操作: # 安装脚手架工具 npm install wepy-cli -g # 创建一个新的项目 npm init standard myproject # 进入新项 ...