Dijkstra is still the most commonly used shortest path algorithm. The code written in the previous study of data structure is very redundant, and I can't remember it. If you have time today, let's put together a concise template!
The implementation method corresponds to the priority queue, and the template includes the method of mapping (in fact, any kind of method is fine). This article uses:
vector< unordered_map<int, int>> graph(n); // 本质是邻接表
The template is as follows:
void DIJ() {
/* 建图,建图方式有几种,尽量使用邻接表
* 1.vector<vector<int>> graph(n) // 临界矩阵
* 2.vector<unordered_map<int,int>> // 邻接表,map中first代表指向,second代表权值
*/
// 假设有vector<vector<int>> edges提供边的信息,[1,2,3]代表1->2,权值为3
vector<unordered_map<int, int>> graph(n);
for (int i=0; i<edges.size(); i++) {
int u = edges[i][0];
int v = edges[i][1];
int w = edges[i][2];
graph[u-1][v-1] = w; // -1的原因是索引从0开始
graph[v-1][u-1] = w; // 看清问题是单向图还是双向图,决定了写几个
}
vector<int> dis(n, INT_MAX);
priority_queue<pair<int, int>, vector<pair<int, int> > > q;
// 起点编号设置为start
dis[start] = 0;
q.push(start, 0);
while (!q.empty()) {
pair<int, int> tp = q.top();
int id = tp.first;
int distance = tp.second;
q.pop();
// 这里用指针吧,用graph[id][i].first会报错,不知道为啥
for (auto it=graph[id].begin(); it != graph[id].end(); it++) {
int new_id = it->first;
int new_distance = it->second;
if (dis[id]+new_distance < dis[new_id]) {
dis[new_id] = dis[id] + new_distance;
q.push(make_pair(new_id, -dis[new_id])); // 传入负值,实现从小到大排列
}
}
}
}
// dis数组中得到的就是起点到各个节点的最短距离了,如果不达就会是INT_MAX
Just say not to practice the fake style, let's try the template with two sample questions!
Exercise 1: P1339 [USACO09OCT] Heat Wave G
The AC code is as follows:
#include<bits/stdc++.h>
using namespace std;
int main(void) {
int n,m,s,t;
cin >> n >> m >> s >> t;
vector<unordered_map<int,int> > graph(n);
for (int i=0; i<m; i++) {
int u,v,w;
cin >> u >> v >>w;
graph[u-1][v-1] = w;
graph[v-1][u-1] = w;
}
vector<int> dis(n, INT_MAX);
priority_queue<pair<int, int>, vector<pair<int, int>>> q;
dis[s-1] = 0;
q.push(make_pair(s-1,0));
while (!q.empty()) {
pair<int, int> tp = q.top();
int id = tp.first;
int distance = tp.second;
q.pop();
for (auto it=graph[id].begin(); it != graph[id].end(); it++) {
int new_id = it->first;
int new_distance = it->second;
if (dis[id] + new_distance < dis[new_id]) {
dis[new_id] = dis[id] + new_distance;
q.push(make_pair(new_id, -dis[new_id]));
}
}
}
cout << dis[t-1];
return 0;
}
Exercise 2: P3371 【Template】Single source shortest path (weakened version)
P3371 [Template] Single source shortest path (weakened version)
In fact, this code did not completely pass the test, but it was written according to the template. Can pass the sample, I don't know what's going on, please help me to answer the questions of the passing gods. Attach the code first, maybe it will happen later?
code show as below:
#include<bits/stdc++.h>
using namespace std;
int main(void) {
int n, m, s;
cin >> n >> m >> s;
vector<unordered_map<int, int>> graph(n);
for (int i=0; i<m; i++) {
int u,v,w;
cin >> u >> v >> w;
graph[u-1][v-1] = w;
}
vector<int> dis(n, INT_MAX);
priority_queue<pair<int,int>,vector<pair<int,int>>> q;
dis[s-1] = 0;
q.push(make_pair(s-1, 0));
while (!q.empty()) {
pair<int, int> pa = q.top();
int id = pa.first;
int distance = pa.second;
q.pop();
for (auto it=graph[id].begin(); it!=graph[id].end(); it++) {
int new_id = it->first;
int new_distance = it->second;
if (dis[id]+new_distance < dis[new_id]) {
dis[new_id] = dis[id]+new_distance;
q.push(make_pair(new_id, -dis[new_id]));
}
}
}
for (int i=0; i<n; i++) {
if (i != n-1)
cout << dis[i] << " ";
else
cout << dis[i];
}
return 0;
}
In fact, the real graph topic DIJ is only part of it, so master part by part, hoping to solve the big problem slowly hhh!
Reference materials:
Dijkstra's algorithm detailed explanation + template + sample questions