迪杰特斯拉还是比较常用的最短路径算法。之前学数据结构时写的代码很冗余,总是记不住。今天有时间,整理出一个简练的模板吧!
实现的方式对应了优先队列,模板中包括建图的方法(其实哪种都可以)。本文用的是:
vector< unordered_map<int, int>> graph(n); // 本质是邻接表
模板如下:
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
光说不练假把式,来两道例题试试模板吧!
练习一:P1339 [USACO09OCT]Heat Wave G
AC代码如下:
#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;
}
练习二:P3371 【模板】单源最短路径(弱化版)
P3371 【模板】单源最短路径(弱化版)
其实这个代码没有完全通过测试,但也是按照模板写的呀。能够通过样例,不知道怎么回事,请路过的大神帮我解答一下吧。先附上代码,说不定以后就会了呢?
代码如下:
#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;
}
其实真正的图论题DIJ只是其中的一部分,那就一部分一部分掌握,希望慢慢能解决大题吧hhh!
参考资料:
迪杰斯特拉算法详解+模版+例题
因作者水平有限,如有错误之处请在下方评论区指正,谢谢!