一、题目链接
二、题目分析
(一)算法标签
最短路 Dijkstra
(二)解题思路
注意是在出队时修改st数组:如果找到了最短路(即st[ver]==true),则continue,接下来st[ver]=true
三、AC代码
解法一:
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
typedef pair<int, int> PII;
const int N = 15e4 + 10;
// 稀疏图用邻接表来存储
int h[N], w[N], e[N], ne[N], idx;
int dist[N];
int n, m;
bool st[N];
void add(int a, int b, int c) {
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;
}
int dijkstra() {
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
priority_queue<PII, vector<PII>, greater<PII>> heap; // 类型, 容器, 比较 (greater表示小根堆)
heap.push({0, 1}); // first 存储距离(因为以距离作为比较,小距离在前), second 存储顶点编号
while (heap.size()) {
auto t = heap.top(); // 每次取距离最短的顶点
heap.pop();
int vertex = t.second, distance = t.first; // vertex: 顶点编号; distance: 编号为vertex的顶点到1号点的最短距离
if (st[vertex]) continue; // 如果编号为vertex的顶点已经找到了最短路
st[vertex] = true;
for (int i = h[vertex]; i != -1; i = ne[i]) {// 用当前点来更新其它点,即遍历编号为vertex的顶点的所有邻边(或者说与之相连的顶点)
int j = e[i]; // 找到顶点编号
if (!st[j] && dist[j] > dist[vertex]/*distance*/ + w[i]) // distance 就是dist[vertex]
dist[j] = dist[vertex]/*distance*/ + w[i];
heap.push({dist[j], j});
}
}
if (dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}
int main() {
memset(h, -1, sizeof h);
cin >> n >> m;
while (m --) {
int x, y, z;
cin >> x >> y >> z;
add(x, y, z); // 由于堆优化版的dijkstra算法本身会确保最短的边, 所以不用处理重边
}
cout << dijkstra();
return 0;
}