Graph Templates
Dijkstra
Dijkstra 算法是(在数据结构优化情况下)在O(mlog_2n)时间复杂度下的单源最短路径算法。
//
// Created by asdf on 1/29/2024.
//
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> ii;
const int N = 1e5 + 10, M = 2e5 + 10;
int dis[N];
bool processed[N];
vector<ii> adj[N];
void dijkstra(int start, int total_node) {
priority_queue<ii, vector<ii>,greater<>> pq; // min-heap
// initialize
fill_n(dis, N,INT_MAX);
// starting node
dis[start] = 0;
pq.emplace(0, start);
while (!pq.empty()) {
int u = pq.top().second;
pq.pop();
//update processed array
if (processed[u])continue;
processed[u] = true;
for (auto &edge: adj[u]) {
int v = edge.second;
int n_dist = edge.first;
// if there is a shorter path to v through u
if (dis[u] + n_dist < dis[v]) {
dis[v] = dis[u] + n_dist;
pq.emplace(dis[v],v);// push the new distance to pq
}
}
}
}
int main() {
int n,m,s;
cin>>n>>m>>s;
for (int i = 0; i < m; ++i) {
int u,v,w;
cin>>u>>v>>w;
adj[u].emplace_back(w,v);
}
dijkstra(s,n);
for(int i=1;i<=n;i++) {
cout<<dis[i]<<' ';
}
return 0;
}
来自2025-1-25的update:
好久没碰算法了重新搓了一遍,发现上面的实现还挺别致的。oi wiki
还有 usaco.guide
上面的实现都是又用结构体定义edge和node:
struct edge {
int v, w;
};
struct node {
int dis, u;
bool operator>(const node& a) const { return dis > a.dis; }
};
vector<edge> e[MAXN];
int dis[MAXN], vis[MAXN];
priority_queue<node, vector<node>, greater<node>> q;
void dijkstra(int n, int s) {
memset(dis, 0x3f, (n + 1) * sizeof(int));
memset(vis, 0, (n + 1) * sizeof(int));
dis[s] = 0;
q.push({0, s});
while (!q.empty()) {
int u = q.top().u;
q.pop();
if (vis[u]) continue;
vis[u] = 1;
for (auto ed : e[u]) {
int v = ed.v, w = ed.w;
if (dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
q.push({dis[v], v});
}
}
}
}
这里我们的 pair<int,int>
既是node也是edge,以下是更新注释后的代码,注意两个DEF(definition):
/* https://www.luogu.com.cn/problem/P4779
* Created by: Friedforks
* Date: 2025-01-25
*/
#include <algorithm>
#include <bits/stdc++.h>
#include <queue>
#include <vector>
using namespace std;
typedef pair<int, int> ii;
const int MAXN = 1e5 + 5, M = 2e5 + 5;
int dis[MAXN];
bool processed[MAXN];
// DEF 1:the pair ii serve as edge <weight, node number>
vector<ii> adj[MAXN];
void dijkstra(int start, int total_node) {
// DEF 2:here the pair ii serve as node <distance, node number>
priority_queue<ii, vector<ii>, greater<>> pq; // min-heap
// initialize the distance all to be infinity
fill_n(dis, MAXN, INT_MAX);
// starting node
dis[start] = 0; // distance to itself is 0
pq.emplace(0, start);
while (!pq.empty()) {
const int u = pq.top().second; // add next node to pq
// update processed array
if (processed[u])
continue;
processed[u] = true;
for (auto &edge : adj[u]) {
int v = edge.second;
const int weight = edge.first;
// if there is a shorter path to v through u
if (dis[u] + weight < dis[v]) {
// update the shorter distance
dis[v] = dis[u] + weight;
// check if already processed
if (!processed[v]) {
pq.emplace(dis[v], v); // push the new distance to pq
}
}
}
}
}
int main() {
int n, m, s; // n node, m edges, s start node
cin >> n >> m >> s;
// input
for (int i = 0; i < m; i++) {
int u, v, w; // u -> v with weight w
cin >> u >> v >> w;
adj[u].emplace_back(w, v);
}
dijkstra(s, n);
for (int i = 1; i <= n; i++) {
cout << dis[i] << ' ';
}
return 0;
}
评论
其他文章