【模板】单源最短路径(Dijkstra)/洛谷P4779

1|0题目链接

https://www.luogu.com.cn/problem/P4779

2|0题目大意

给定一个 n 个点 m 条边有向图,每个点有一个非负权值,求从 s 点出发,到每个点的最短距离。

数据保证能从 s 出发到任意点。

3|0题目解析

朴素的 Dijkstra 算法时间复杂度为 O(n2)

使用优先队列 priority_queue 模拟小根堆(需要重定义)实现堆优化,每次查找最小值时间复杂度减小至 O(logn)

时间复杂度 O(nlogn)

完整的参考代码中采用的是 pair<int,int> 作为优先队列节点的比较容器,这种容器相当于包含两个参量的结构体,
比较顺序是:先比较第一个参量 (first) ,再比较第二个参量 (second)

当然也可以采用自定义结构体的方式,重载运算符后进行比较,下面也提供了三种较为常用的参考方法。

4|0参考代码

#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; }

5|0自定义结构体的方法

方法1

由于优先队列 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

在结构体内部将重载“大于号”,并在 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;

谢谢支持!


__EOF__

本文作者炯炯目光
本文链接https://www.cnblogs.com/jjmg/p/14053525.html
关于博主:KTH 信息与网络工程硕士在读
版权声明:欢迎分享或转载
声援博主:To be or not to be, is a question.
posted @   Chiron-zy  阅读(138)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示