1 条题解
-
0
朴素的 Dijkstra 算法
- 初始化:除了起点之外,最短路都是无穷大,所有点都还没确定
- 不停地去确定还没确定的点
- 找到还没确定的点中最近的一个
- 标记这个点已经确定了
- 用这个点优化相邻的点
- 尝试用
dis[u]+w
来优化 dis[v]
- 尝试用
#include <bits/stdc++.h> #define int long long using namespace std; // 因为会用到 INF+x,所以务必保证 INF+INF 不会溢出,否则就要特判 const int INF = 1LL * 300'000 * 1'000'000'000; const int MAXN = 300000; const int MAXM = 300000; int n, m; vector<pair<int, int>> e[MAXN + 5]; int dis[MAXN + 5]; // 起点到每个点的最短路 bool vis[MAXN + 5]; // 是否确定下来了 signed main() { ios::sync_with_stdio(false); cin.tie(0); // 输入存图 cin >> n >> m; for (int i = 1; i <= m; i++) { int u, v, w; cin >> u >> v >> w; e[u].push_back({v, w}); } // Dijkstra 算法 for (int i = 1; i <= n; i++) { dis[i] = INF; vis[i] = false; } dis[1] = 0; while (1) { int u = -1; for (int i = 1; i <= n; i++) if (vis[i] == false && (u == -1 || dis[i] < dis[u])) u = i; if (u == -1) break; vis[u] = true; for (int i = 0; i < e[u].size(); i++) { int v = e[u][i].first; int w = e[u][i].second; dis[v] = min(dis[v], dis[u] + w); } } for (int i = 1; i <= n; i++) if (dis[i] == INF) cout << -1 << " "; else cout << dis[i] << " "; return 0; }
优先队列优化的 Dijkstra 算法
- 初始化:除了起点之外,最短路都是无穷大,所有点都还没确定
- 把起点放入优先队列
- 只要优先队列还有东西,就继续优化
- 取出当前最近的
- 如果这个点已经被确定了,就跳过这个点
- 如果没有确定,这个点可以确定下来了,不可能被优化了
- 用这个点优化相邻的点
- 尝试用
dis[u]+w
来优化 dis[v]
- 尝试用
#include <bits/stdc++.h> #define int long long using namespace std; // 因为会用到 INF+x,所以务必保证 INF+INF 不会溢出 // 实际上也可以用 -1 表示无法到达,然后特判 -1 即可 const int INF = 1LL * 300'000 * 1'000'000'000; const int MAXN = 300000; const int MAXM = 300000; int n, m; vector<pair<int, int>> e[MAXN + 5]; int dis[MAXN + 5]; // 起点到每个点的最短路 bool vis[MAXN + 5]; // 是否确定下来了 // 存 <-dis[i],i> 来保证每次都能拿出来最近的点 priority_queue<pair<int, int>> q; signed main() { ios::sync_with_stdio(false); cin.tie(0); // 输入存图 cin >> n >> m; for (int i = 1; i <= m; i++) { int u, v, w; cin >> u >> v >> w; e[u].push_back({v, w}); } // Dijkstra 算法 for (int i = 1; i <= n; i++) { dis[i] = INF; vis[i] = false; } dis[1] = 0; q.push({-dis[1], 1}); while (!q.empty()) { int u = q.top().second; q.pop(); if (vis[u]) continue; vis[u] = true; for (int i = 0; i < e[u].size(); i++) { int v = e[u][i].first; int w = e[u][i].second; if (dis[u] + w < dis[v]) { dis[v] = dis[u] + w; q.push({-dis[v], v}); } } } for (int i = 1; i <= n; i++) if (dis[i] == INF) cout << -1 << " "; else cout << dis[i] << " "; return 0; }
- 1
信息
- ID
- 8595
- 时间
- 2000ms
- 内存
- 512MiB
- 难度
- 3
- 标签
- (无)
- 递交数
- 11
- 已通过
- 4
- 上传者