dijkstra:单源最短路
每次取出离起点最近的点,以这个点为中转站,尝试更新其它结点
#include <bits/stdc++.h>
using namespace std;
int n, m, s, t;
int g[3000][3000];
bool r[3000];
int main() {
cin >> n >> m >> s >> t;
memset(g, 0x3f, sizeof g);
memset(r, 0, sizeof r);
for (int i = 0; i < m; i++) {
int si, ti, wi;
cin >> si >> ti >> wi;
g[si][ti] = min(g[si][ti], wi);
g[ti][si] = min(g[ti][si], wi);
}
for (int i = 0; i < n; i++) {
int pos = -1, md = 1e9;
for (int j = 1; j <= n; j++) {
if (r[j] == false && md >= g[s][j]) {
md = g[s][j];
pos = j;
}
}
if (pos == -1) break;
r[pos] = true;
for (int j = 1; j <= n; j++) {
g[s][j] = min(g[s][j], g[s][pos] + g[pos][j]);
}
}
cout << g[s][t] << endl;
return 0;
}
时间复杂度:O(),其中n为点的个数
堆优化 dijkstra:
与上述算法思想相同,用小根堆优化找中转站的过程
#include <bits/stdc++.h>
using namespace std;
int n, m, s, t;
vector<int> dist(3000, 1e9);
vector<vector<pair<int, int>>> g(3000);
int main() {
cin >> n >> m >> s >> t;
for (int i = 0; i < m; i++) {
int si, ti, wi;
cin >> si >> ti >> wi;
g[si].push_back({ti, wi});
g[ti].push_back({si, wi});
}
dist[s] = 0;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> q;
q.push({0, s});
while (!q.empty()) {
auto [u, t] = q.top();
q.pop();
if (u > dist[t]) continue;
for (auto [v, w] : g[t]) {
if (u + w < dist[v]) {
dist[v] = u + w;
q.push({u + w, v});
}
}
}
cout << dist[t] << endl;
return 0;
}
时间复杂度:O(),其中m为边的条数
floyd:多源最短路
第一重循环枚举中转站,第二重循环枚举起点,第三重循环枚举终点
#include <bits/stdc++.h>
using namespace std;
int g[505][505];
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> g[i][j];
}
}
for (int k = 0; k < n; k++) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
}
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cout << g[i][j] << ' ';
}
cout << endl;
}
return 0;
}
时间复杂度:O(),其中n为点的个数
SPFA:
#include <bits/stdc++.h>
using namespace std;
int n, m, s, t, dist[3000];
bool vis[3000];
vector<vector<pair<int, int>>> g(3000);
int main() {
cin >> n >> m >> s >> t;
for (int i = 0; i < m; i++) {
int si, ti, wi;
cin >> si >> ti >> wi;
g[si].push_back({ti, wi});
g[ti].push_back({si, wi});
}
memset(dist, 0x3f, sizeof dist);
dist[s] = 0, vis[s] = 1;
queue<int> q;
q.push(s);
while (!q.empty()) {
int u = q.front();
q.pop(), vis[u] = 0;
for (auto [v, w] : g[u]) {
if (dist[v] > dist[u] + w) {
dist[v] = dist[u] + w;
if (!vis[v]) {
q.push(v);
vis[v] = 1;
}
}
}
}
cout << dist[t] << endl;
return 0;
}
时间复杂度:O(),k是一个较小的常数,m是边的条数,最坏情况下会被卡成O()