[CF20C] Dijkstra? - 最短路
Description
给出一张图,请输出其中任意一条可行的从点 1 到点 n 的最短路径。
Solution
(当作是复习数据结构,默一遍 Dijkstra 板子)
Dijkstra 的核心思想是维护一个已经处理过的集合 S,每次选择一个 (p otin S) 的 (dist[p]) 最小的 p,将它加入集合 S 中,并且更新所有 p 的直接后继的距离。
实现中,我们用堆来加速查找最小值的过程。具体地,我们在小顶堆中压入 (距离,顶点) 的结构,每次松弛操作后都压入(这样可能会导致堆中出现重复元素,没有关系,只要我们通过 (vis[]) 保证每个点只会被访问一次即可)。
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
ios::sync_with_stdio(false);
int n;
int m;
cin >> n >> m;
vector<int> vis(n + 2, 0), dis(n + 2, (long long)(1e18)), from(n + 2, 0);
vector<tuple<int, int, int>> edges;
vector<vector<pair<int, int>>> g(n + 2, vector<pair<int, int>>());
for (int i = 1; i <= m; i++)
{
int t1, t2, t3;
cin >> t1 >> t2 >> t3;
edges.emplace_back(make_tuple(t1, t2, t3));
g[t1].emplace_back(make_pair(t2, t3));
g[t2].emplace_back(make_pair(t1, t3));
}
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> que;
dis[1] = 0;
que.push(make_pair(dis[1], 1));
while (!que.empty())
{
auto [d, p] = que.top();
que.pop();
if (vis[p])
continue;
vis[p] = 1;
for (auto [q, w] : g[p])
{
if (dis[p] + w < dis[q])
{
dis[q] = dis[p] + w;
from[q] = p;
que.push(make_pair(dis[q], q));
}
}
}
function<void(int)> print = [&](int p) -> void {
if (p)
{
print(from[p]);
cout << p << " ";
}
};
if (dis[n] < 1e17)
{
print(n);
}
else
{
cout << -1;
}
}