【模板】单源最短路径(Dijkstra)/洛谷P4779
题目链接
https://www.luogu.com.cn/problem/P4779
题目大意
给定一个 \(n\) 个点 \(m\) 条边有向图,每个点有一个非负权值,求从 \(s\) 点出发,到每个点的最短距离。
数据保证能从 \(s\) 出发到任意点。
题目解析
朴素的 \(\mathrm{Dijkstra}\) 算法时间复杂度为 \(O(n^2)\)。
使用优先队列 \(\mathrm{priority\_queue}\) 模拟小根堆(需要重定义)实现堆优化,每次查找最小值时间复杂度减小至 \(O(\log n)\)。
时间复杂度 \(O(n \log n)\)
完整的参考代码中采用的是 \(\mathrm{pair<int,int>}\) 作为优先队列节点的比较容器,这种容器相当于包含两个参量的结构体,
比较顺序是:先比较第一个参量 \((\mathrm{first})\) ,再比较第二个参量 \((\mathrm{second})\) 。
当然也可以采用自定义结构体的方式,重载运算符后进行比较,下面也提供了三种较为常用的参考方法。
参考代码
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1e5+5;
int n, m, s, dis[N];
priority_queue <pair<int, int>, vector <pair<int, int> >, greater<pair<int, int> > > Q;
vector <pair<int, int> > e[N];
inline int read()
{
int X=0; bool flag=1; char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
if(flag) return X;
return ~(X-1);
}
void Dijkstra()
{
dis[s] = 0;
Q.push(make_pair(0, s));
while (!Q.empty()){
int a = Q.top().second, c = Q.top().first;
Q.pop();
if (c != dis[a]) continue;
for (int i=0; i<e[a].size(); i++){
int b = e[a][i].second;
if (dis[b] > dis[a]+e[a][i].first){
dis[b] = dis[a]+e[a][i].first;
Q.push(make_pair(dis[b], b));
}
}
}
}
int main()
{
int a, b, c;
n=read(), m=read(), s=read();
for (int i=0; i<m; ++i) {
a=read(), b=read(), c=read();
e[a].push_back(make_pair(c, b));
}
for (int i=1; i<=n; ++i) dis[i] = INF;
Dijkstra();
for (int i=1; i<=n; ++i) printf("%d ", dis[i]);
putchar('\n');
return 0;
}
自定义结构体的方法
方法1:
由于优先队列 \(\mathrm{priority\_queue}\) 默认为大根堆,因此在结构体内部将“小于号”重载为“大于比较”即可,这是最简单的定义方法。
但是由于大小比较的不统一,往往容易引入其他由于混淆产生的错误或者带来检查上的困难。因此如这个结构体需要在代码内重复利用到的,则不推荐使用这种方法。
struct node{
int c, a;
bool operator < (const node &A) const {
return c > A.c;//注意此处为大于号!
}
};
priority_queue <node> Q;
//与priority_queue <node, vector<node>, less<node> > Q;等价
//其中std::less<Type>()为内置的小于比较类
方法2:
在结构体内部将重载“大于号”,并在 \(\mathrm{priority\_queue}\) 中采用 \(std::greater<Type>()\) (大于比较类)来成为小根堆,这样在大小比较上是统一的。
struct node{
int c, a;
bool operator > (const node &A) const {
return c > A.c;
}
};
priority_queue <node, vector<node>, greater<node> > Q;
方法3:
用自定义类来实现比较。
struct node{
int c, a;
};
struct cmp{
//操作符重载函数,必须是写()
bool operator () (const node &A, const node &B){
return A.c > B.c;//小根堆
}
};
priority_queue <node, vector<node>, cmp> Q;
谢谢支持!
【模板】单源最短路径(Dijkstra)/洛谷P4779的更多相关文章
- 单源最短路径Dijkstra算法,多源最短路径Floyd算法
1.单源最短路径 (1)无权图的单源最短路径 /*无权单源最短路径*/ void UnWeighted(LGraph Graph, Vertex S) { std::queue<Vertex&g ...
- [数据结构与算法-15]单源最短路径(Dijkstra+SPFA)
单源最短路径 问题描述 分别求出从起点到其他所有点的最短路径,这次主要介绍两种算法,Dijkstra和SPFA.若无负权优先Dijkstra算法,存在负权选择SPFA算法. Dijkstra算法 非负 ...
- 单源最短路径——dijkstra算法
dijkstra算法与prim算法的区别 1.先说说prim算法的思想: 众所周知,prim算法是一个最小生成树算法,它运用的是贪心原理(在这里不再证明),设置两个点集合,一个集合为要求的生成树的 ...
- 单源最短路径 dijkstra算法实现
本文记录一下dijkstra算法的实现,图用邻接矩阵表示,假设图为无向图.而且连通,有向图,不连通图的做法相似. 算法简述: 首先确定"单源"的源.假设是第0个顶点. 维护三个数组 ...
- matlab练习程序(单源最短路径Dijkstra)
图的相关算法也算是自己的一个软肋了,当年没选修图论也是一大遗憾. 图像处理中,也有使用图论算法作为基础的相关算法,比如图割,这个算法就需要求最大流.最小割.所以熟悉一下图论算法对于图像处理还是很有帮助 ...
- 洛谷P3371单源最短路径Dijkstra堆优化版及优先队列杂谈
其实堆优化版极其的简单,只要知道之前的Dijkstra怎么做,那么堆优化版就完全没有问题了. 在做之前,我们要先学会优先队列,来完成堆的任务,下面盘点了几种堆的表示方式. priority_queue ...
- 洛谷P3371单源最短路径Dijkstra版(链式前向星处理)
首先讲解一下链式前向星是什么.简单的来说就是用一个数组(用结构体来表示多个量)来存一张图,每一条边的出结点的编号都指向这条边同一出结点的另一个编号(怎么这么的绕) 如下面的程序就是存链式前向星.(不用 ...
- 【洛谷 p3371】模板-单源最短路径(图论)
题目:给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 解法:spfa算法. 1 #include<cstdio> 2 #include<cstdlib> 3 #in ...
- [模板]单源最短路径(Dijkstra)
如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 主要还是再打一遍最短路,这种算法我用的不多... #include<bits/stdc++.h> using namesp ...
- luogu3371 【模板】单源最短路径 dijkstra堆优化
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> ...
随机推荐
- 从零开始的DIY智能家居 - 基于 ESP32 的智能浇水器
前言 上次 土壤湿度传感器 完成之后,就立下一个 flag 要搭建一个智慧浇水的智能场景,现在终于有时间填坑了!(o゚▽゚)o 智慧浇水场景的核心设备有三个: 检测土壤状态的:土壤湿度传感器 通过这个 ...
- 手把手教你学Dapr - 4. 服务调用
上一篇:手把手教你学Dapr - 3. 使用Dapr运行第一个.Net程序 介绍 通过使用服务调用,您的应用程序可以使用标准的gRPC或HTTP协议与其他应用程序可靠.安全地通信. 为什么不直接用Ht ...
- Vue脚手架最新版本安装使用
现在很多的插件如Vant 这类的样式框架,都去兼容了Vue的3.0版本,所以我总结一下如何去简单的搭建一个Vue3.0的框架 开始 一,如何安装 在这里说明一下,Vue脚手架版本,和Vue版本是两个东 ...
- DeWeb - 物资流转管理系统 - 开发1
近期一个朋友提到要做一个安卓手机上物资流转管理系统 准备采用deweb练练手! 大致的计划是先做成手机版网页,然后加壳做成APP 一. 登录 界面基本设计如下 用户表设计如下: 待续
- Linux使用ssh测试端口
在windows上可以使用telnet客户端测试,在linux如果不方便安装telnet客户端的时候可以通关ssh来测试端口 具体命令如下 ssh -v -p 8080 root@59.207.252 ...
- 基于 OSPF 路由的邻居邻接关系发现实践
1.实验目的 理解 OSPF 邻居关系和 OSPF 邻接关系的含义及差别 观察 OSPF 邻居邻接关系的建立过程 观察 OSPF 链路状态数据库的同步过程 2.实验原理 OSPF 网络中,路由器在发送 ...
- 重装系统——联想window 10
大四了,读了四年大学,唉,混的,啥也不会,工作也找不到,真的不知道这大学四年到底干了什么.专业是计算机方向的,但居然,不敢,也不会装电脑系统,大学四年的文件都是乱放的,更那个的是,有些软件卸载不完全, ...
- MySQL、Oracle批量插入SQL的通用写法
举个例子: 现在要批量新增User对象到数据库USER表中 public class User{ //姓名 private String name; //年龄 private Integer age; ...
- BAT面试必问细节:关于Netty中的ByteBuf详解
在Netty中,还有另外一个比较常见的对象ByteBuf,它其实等同于Java Nio中的ByteBuffer,但是ByteBuf对Nio中的ByteBuffer的功能做了很作增强,下面我们来简单了解 ...
- IDEA安装热部署插件JRebel
首先说下热部署是什么意思吧,简单了说就是在我们对代码进行更改之后,不需要重启项目,重新编译一下就可以直接运行最新的代码的部署方式.既然是部署方式,项目启动部署的时候当然就会和正常情况下不一样啦~ JR ...