dijkstra(学习笔记)
dijkstra(练习笔记)
概述
- 用于单源最短路径求解
- 非负权图
- 使用贪心理念,先把最小的跑完,有两种做法,一个n^2一个m log m,第二种使用堆优化先跑最小的,刚好不需要n方遍历
- 其实堆优化理念和BFS(优先队列优化版)很像
堆优化实现
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5*5+10;
const int M = 1e4+10;
int n, m, s;
//建图
int cnt, h[M];
struct Node {
int to, next, w;
}e[2*N];
void add(int u, int v, int w) {
e[++cnt].to = v;
e[cnt].next = h[u];
e[cnt].w = w;
h[u] = cnt;
}
//定义一个重构的结构体
struct node {
//dis表示到u点的最小值
int dis, u;
//返回F/T表示当下的dis与另一个数比较,const表示不会改变当前的数
//声明禁止修改,但是可以访问,末尾的const是声明前面函数的成员元素禁止修改
//然后是在这个重构函数里进行比较大小的,直接用dis和新node下比较
//const对象是不能调用非const的成员函数的
bool operator<(const node& a) const { return dis > a.dis; }
};
//Dijkstra(总点数,s为起点)
//定义dis和vis分别表示为最短路和是否为最值最小
int dis[M], vis[M];
//定义一个优先队列做优化
priority_queue<node> q;
void Dij(int n, int s) {
memset(vis, 0, sizeof(vis));
memset(dis, 0x3f, sizeof(dis));
dis[s] = 0;//当前最小值是0
q.push({0,s});
while (!q.empty()) {
int u = q.top().u;
q.pop();
//因为用了堆优化,没必要去做n^2模拟去找那个最小未确定节点
//每次去找最小未确定节点,最后可以得到最好的优化
vis[u] = 1;
for (int i = h[u]; i!=0; i = e[i].next) {
int v = e[i].to, w = e[i].w;
//去寻找更小的边去更新
if (dis[v]>dis[u] + w) {
dis[v] = dis[u] + w;
q.push({dis[v], v});
}
}
}
}
int main() {
cin >> n >> m >> s;
for (int i=1; i<=m; i++) {
int u, v, w;
cin >> u >> v >> w;
add(u, v, w);
// add(v, u, w);
}
Dij(n, s);
for (int i=1; i<=n; i++) {
if (dis[i]==0x3f3f3f3f) {
cout<<2147483647<<" ";
continue;
}
cout << dis[i] << " ";
}
return 0;
}
其实还顺便学了一下const和重构运算符