P1339 [USACO09OCT] Heat Wave G 最短路入门题 Dijkstra/SPFA/Dijkstra+优先队列优化
题目链接:https://www.luogu.com.cn/problem/P1339
题目大意:无向图有单源最短路。
朴素的 Dijkstra 算法
时间复杂度 \(O(n^2)\)。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2505;
struct Edge { int v, w; };
vector<Edge> g[maxn];
int n, m, s, t;
// 朴素版 Dijkstra
int dis[maxn];
bool vis[maxn];
void dijkstra() {
memset(dis, 0x3f, sizeof(int)*(n+1));
dis[s] = 0;
for (;;) {
int u = 0;
for (int i = 1; i <= n; i++)
if (!vis[i] && (!u || dis[i] < dis[u]))
u = i;
if (!u)
break;
vis[u] = true;
for (auto e : g[u]) {
int v = e.v, w = e.w;
dis[v] = min(dis[v], dis[u] + w);
}
}
}
int main() {
scanf("%d%d%d%d", &n, &m, &s, &t);
for (int i = 0; i < m; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
g[u].push_back({v, w});
g[v].push_back({u, w});
}
dijkstra();
printf("%d\n", dis[t]);
return 0;
}
SPFA 算法
时间复杂度 \(O(nm)\),但是一般会很快。但是 OI 慎用!因为数据极有可能会卡 SPFA。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2505;
struct Edge { int v, w; };
vector<Edge> g[maxn];
int n, m, s, t;
// SPFA
int dis[maxn];
bool inq[maxn]; // 判断是否在队列中
void dijkstra() {
queue<int> que;
memset(dis, 0x3f, sizeof(int)*(n+1));
dis[s] = 0;
que.push(s);
while (!que.empty()) {
int u = que.front();
que.pop();
inq[u] = false;
for (auto e : g[u]) {
int v = e.v, w = e.w;
if (dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
if (!inq[v])
inq[v] = true, que.push(v);
}
}
}
}
int main() {
scanf("%d%d%d%d", &n, &m, &s, &t);
for (int i = 0; i < m; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
g[u].push_back({v, w});
g[v].push_back({u, w});
}
dijkstra();
printf("%d\n", dis[t]);
return 0;
}
Dijkstra + 优先队列优化
时间复杂度 \(O(m \log m)\),建议使用(好像还有 Dijkstra + 堆优化的,但是目前还不会,不过 \(O(m \log m)\) 已经基本够用了)
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2505;
struct Edge { int v, w; };
vector<Edge> g[maxn];
int n, m, s, t;
// Dijkstra + 优先队列优化
struct Node {
int u, dis;
bool operator < (const Node &b) const {
return dis > b.dis;
}
};
int dis[maxn];
bool vis[maxn];
void dijkstra_pq() {
priority_queue<Node> que;
memset(dis, 0x3f, sizeof(int)*(n+1));
dis[s] = 0;
que.push({s, 0});
while (!que.empty()) {
Node nd = que.top();
que.pop();
int u = nd.u, _dis = nd.dis;
if (vis[u]) continue;
vis[u] = true;
for (auto e : g[u]) {
int v = e.v, w = e.w;
if (vis[v]) continue;
if (dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
que.push({v, dis[v]});
}
}
}
}
int main() {
scanf("%d%d%d%d", &n, &m, &s, &t);
for (int i = 0; i < m; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
g[u].push_back({v, w});
g[v].push_back({u, w});
}
dijkstra_pq();
printf("%d\n", dis[t]);
return 0;
}