洛谷 P1629 邮递员送信 (三种最短路+SPFA)

邮递员送信 - 洛谷

题意容易理解,从1出发到其他所有点并返回的最短路,需要先正着跑一边,然后建反边再跑一边

Dijkstra:

#include <bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<n;i++)
using namespace std;
using LL = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m;
    cin >> n >> m;
    vector<vector<pair<int, int>>> G(n + 1), G1(n + 1);
    vector<int> dist(n + 1, 0x3f3f3f3f), dist1(n + 1, 0x3f3f3f3f);
    rep (i, 0, m) {
        int u, v, c;
        cin >> u >> v >> c;
        G[u].push_back(make_pair(v, c));
        G1[v].push_back(make_pair(u, c));
    }
    LL ans = 0;
    dist[1] = 0;
    set<pair<int, int>> se, se1;
    for (int i = 1; i <= n; i++) {
        se.insert(make_pair(dist[i], i));
    }
    while (!se.empty()) {
        int u = se.begin()->second;
        se.erase(se.begin());
        if (dist[u] > 1 << 30) {
            break;
        }
        for (auto v : G[u]) {
            if (dist[u] + v.second < dist[v.first]) {
                se.erase(make_pair(dist[v.first], v.first));
                dist[v.first] = dist[u] + v.second;
                se.insert(make_pair(dist[v.first], v.first));
            }
        }
    }
    for (int i = 1; i <= n; i++) {
        ans += dist[i];
    }
    dist1[1] = 0;
    for (int i = 1; i <= n; i++) {
        se1.insert(make_pair(dist1[i], i));
    }
    while (!se1.empty()) {
        int u = se1.begin()->second;
        se1.erase(se1.begin());
        if (dist1[u] > 1 << 30) {
            break;
        }
        for (auto v : G1[u]) {
            if (dist1[u] + v.second < dist1[v.first]) {
                se1.erase(make_pair(dist1[v.first], v.first));
                dist1[v.first] = v.second + dist1[u];
                se1.insert(make_pair(dist1[v.first], v.first));
            }
        }
    }
    for (int i = 1; i <= n; i++) {
        ans += dist1[i];
    }
    cout << ans << '\n';

    return 0;
}

bellman ford:

#include <bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<n;i++)
using namespace std;
using LL = long long;

struct Edge {
    int x, y, v;
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m;
    cin >> n >> m;
    vector<Edge> G(m + 1), G1(m + 1); 
    for (int i = 1; i <= m; i++) {
        int u, v, c;
        cin >> u >> v >> c;
        G[i].x = u;
        G[i].y = v;
        G[i].v = c;
        G1[i].x = v;
        G1[i].y = u;
        G1[i].v = c;
    }
    vector<int> dist(n + 1, 0x3f3f3f3f);
    dist[1] = 0;
    while (true) {
        bool ok = false;
        for (int i = 1; i <= m; i++) {
            int x = G[i].x, y = G[i].y, w = G[i].v;
            if (dist[x] < 1 << 30) {
                if (dist[x] + w < dist[y]) {
                    dist[y] = dist[x] + w;
                    ok = true;
                }
            }
        }
        if (!ok) {
            break;
        }
    }
    vector<int> dist1(n + 1, 0x3f3f3f3f);
    dist1[1] = 0;
    while (true) {
        bool ok = false;
        for (int i = 1; i <= m; i++) {
            int x = G1[i].x, y = G1[i].y, w = G1[i].v;
            if (dist1[x] < 1 << 30) {
                if (dist1[x] + w < dist1[y]) {
                    dist1[y] = w + dist1[x];
                    ok = true;
                }
            }
        }
        if (!ok) {
            break;
        }
    }
    LL ans = 0;
    for (int i = 2; i <= n; i++) {
        ans += dist1[i] + dist[i];
    }
    cout << ans << '\n';

    return 0;
}

floyd (n>=1000慎用,该题吸氧可过):

#include <bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<n;i++)
using namespace std;
using LL = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m;
    cin >> n >> m;
    vector<vector<int>> a(n + 1, vector<int> (n + 1, 0x3f3f3f3f));
    rep (i, 0, m) {
        int u, v, c;
        cin >> u >> v >> c;
        a[u][v] = min(a[u][v], c);
    }
    for (int k = 1; k <= n; k++) {
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                a[i][j] = min(a[i][j], a[i][k] + a[k][j]);
            }
        }
    }
    LL ans = 0;
    for (int i = 2; i <= n; i++) {
        ans = ans + a[1][i] + a[i][1];
    }
    cout << ans << '\n';

    return 0;
}

关于spfa,它已经死了,请不要在任何公共场合写spfa

SPFA:

#include <bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<n;i++)
using namespace std;
using LL = long long;
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
 
    int n, m;
    cin >> n >> m;
    vector<vector<pair<int, int>>> G(n + 1), G1(n + 1);
    vector<int> dist(n + 1, 0x3f3f3f3f);
    vector<int> dist1(n + 1, 0x3f3f3f3f);
    vector<bool> used(n + 1);
    vector<bool> used1(n + 1);
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        G[u].push_back(make_pair(v, w));
        G1[v].push_back(make_pair(u, w));
    }
    int ans = 0;
    queue<int> qu;
    qu.push(1);
    dist[1] = 0;
    used[1] = true;
    while (!qu.empty()) {
        int u = qu.front();
        qu.pop();
        used[u] = true;
        for (auto v : G[u]) {
            if (dist[v.first] > dist[u] + v.second) {
                dist[v.first] = dist[u] + v.second;
                if (!used[v.first]) {
                    used[v.first] = true;
                    qu.push(v.first);
                }
            }
        }
        used[u] = false;
    }
    qu.push(1);
    dist1[1] = 0;
    used1[1] = true;
    while (!qu.empty()) {
        int u = qu.front();
        qu.pop();
        used1[u] = false;
        for (auto v : G1[u]) {
            if (dist1[v.first] > dist1[u] + v.second) {
                dist1[v.first] = dist1[u] + v.second;
                if (!used1[v.first]) {
                    used1[v.first] = true;
                    qu.push(v.first);
                }
            }
        }
    }
    for (int i = 1; i <= n; i++) {
        ans += dist[i] + dist1[i];
    }
    cout << ans << '\n';
 
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值