专栏文章
SP23132 题解
SP23132题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mioslv7y
- 此快照首次捕获于
- 2025/12/03 00:28 3 个月前
- 此快照最后确认于
- 2025/12/03 00:28 3 个月前
题目分析
很明显,这是一道单源最短路的题,可以使用 Dijkstra 来做这道题(如果是骗分的也可以试试 Floyd),而且还可以说这就是一道 Dijkstra 的版子。
接下来我将会简单说一下 Dijkstra。
Dijkstra
这个算法可以简单概括为“Dijkstra = BFS + 贪心”,大体步骤如下:
| 步骤 | 做法 | 具体操作 | 结果 |
|---|---|---|---|
| 从起点 出发,用 BFS 扩展它的邻居节点 | 把这些邻居点放到一个集合 中,并记录这些点到 的距离 | ||
| 选择距离 最近的邻居 ,继续用 BFS 扩展 的邻居 | 首先在 中找到距离 最小的点 ,把 的邻居点放到 中;如果 的邻居经过 中转,到 的距离更短,则更新这些邻居到 的距离;最后从集合 中移走 ,后面不再处理 | 得到了从 到 的最短路径; 的邻居更新了到 的距离 | |
| 重复步骤 ,直到所有点都扩展到并计算完毕 | 集合 为空。计算出所有点到 的最短距离 |
按照这个步骤,实现 Dijkstra 其实并不难,现在给出参考实现代码。
实现
暴力做法()
CPPstruct edge {
int v, w;
};
vector<edge> e[MAXN];
int dis[MAXN], vis[MAXN];
void dijkstra(int n, int s) {
memset(dis, 0x3f, (n + 1) * sizeof(int));
dis[s] = 0;
for (int i = 1; i <= n; i++) {
int u = 0, mind = 0x3f3f3f3f;
for (int j = 1; j <= n; j++)
if (!vis[j] && dis[j] < mind) u = j, mind = dis[j];
vis[u] = true;
for (auto ed : e[u]) {
int v = ed.v, w = ed.w;
if (dis[v] > dis[u] + w) dis[v] = dis[u] + w;
}
}
}
优先队列做法()
CPPstruct edge {
int v, w;
};
struct node {
int dis, u;
bool operator>(const node& a) const { return dis > a.dis; }
};
vector<edge> e[MAXN];
int dis[MAXN], vis[MAXN];
priority_queue<node, vector<node>, greater<node>> q;
void dijkstra(int n, int s) {
memset(dis, 0x3f, (n + 1) * sizeof(int));
memset(vis, 0, (n + 1) * sizeof(int));
dis[s] = 0;
q.push({0, s});
while (!q.empty()) {
int u = q.top().u;
q.pop();
if (vis[u]) continue;
vis[u] = 1;
for (auto ed : e[u]) {
int v = ed.v, w = ed.w;
if (dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
q.push({dis[v], v});
}
}
}
}
Dijkstra 总体上就这些内容了,那么接下来就可以编码了。
参考代码
CPP#include<bits/stdc++.h>
#define int long long
#define Rint register int
#define fast_running ios::sync_with_stdio(false),std::cin.tie(nullptr),std::cout.tie(nullptr)
using namespace std;
typedef pair<int, int> PII;
const int N = 1e5 + 5, M = 1e5 + 5;
const int INF = 0x3f3f3f3f;
int m, s, cnt;
int head[N], dist[N], flag[N];
priority_queue<PII, vector<PII>, greater<PII>> q; //优先队列优化
struct edge {
int from, to, next, w;
} e[M << 1];
void addedge(int u, int v, int w) { //建图
e[++cnt].from = u;
e[cnt].to = v;
e[cnt].next = head[u];
e[cnt].w = w;
head[u] = cnt;
}
void init() { //初始化
for (int i = 0; i < N; i++) {
head[i] = -1;
flag[i] = 0;
dist[i] = INF;
}
cnt = 0;
return;
}
void dijshort(int start) { //优先队列优化的 Dijkstra
dist[start] = 0;
q.push({dist[start], start});
while (!q.empty()) {
PII tp = q.top();
q.pop();
int id_x = tp.second, dist_x = tp.first;
if (flag[id_x]) continue;
flag[id_x] = 1;
for (int i = head[id_x]; i != -1; i = e[i].next) {
int v = e[i].to;
if (dist[v] > dist_x + e[i].w) {
dist[v] = dist_x + e[i].w;
q.push({dist[v], v});
}
}
}
}
signed main() {
fast_running;
cin >> m;
init();
for (int i = 1; i <= m; i++) {
int u, v, w;
cin >> u >> v >> w;
addedge(u, v, w);
addedge(v, u, w);
}
cin >> s;
dijshort(s);
int T, in;
cin >> T;
while (T--) {
cin >> in;
if (dist[in] == INF) cout << "NO PATH\n";
else cout << dist[in] << '\n';
}
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...