最短路算法

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^{2}),其中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\log m),其中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^3),其中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(km),k是一个较小的常数,m是边的条数,最坏情况下会被卡成O(nm)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值