最短路

dijkstra

#include <iostream>
#include <vector>
#include <queue>
#include <cstring>

using namespace std;

int n, m, s, a, b, c;
const int MAXN = 100010;
struct 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; // q{dis,u}

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});
            }
        }
    }
}
int main()
{
    cin >> n >> m >> s;
    for (int i = 0; i < m; i++)
    {
        cin >> a >> b >> c;
        e[a].push_back({b, c});
    }
    dijkstra(n, s);
    for (int i = 1; i <= n; i++)
        cout << dis[i] << " ";
    return 0;
}

P4779 [模板]单源最短路径

SPFA

#include <iostream>
#include <cstring>
#include <queue>

using namespace std;

const int MAXN = 1000010;
int n, m;
struct edge
{
    int v, w;
};
vector<edge> e[MAXN];
int dis[MAXN], cnt[MAXN], vis[MAXN];
queue<int> q;

bool spfa(int n, int s)
{
    memset(dis, 0x3f, (n + 1) * sizeof(int));
    memset(cnt, 0, (n + 1) * sizeof(int));
    memset(vis, 0, (n + 1) * sizeof(int));
    dis[s] = 0, vis[s] = 1;
    q.push(s);
    while (!q.empty())
    {
        int u = q.front();
        q.pop();
        vis[u] = 0; // 出队后取消标记
        for (auto ed : e[u])
        {
            int v = ed.v, w = ed.w;
            if (dis[v] > dis[u] + w)
            {
                dis[v] = dis[u] + w;
                cnt[v] = cnt[u] + 1; // 最短路经过的边数
                if (cnt[v] >= n)     // 最短路边数大于等于n显然有负环
                    return false;
                if (!vis[v])
                {
                    q.push(v);
                    vis[v] = 1;
                }
            }
        }
    }
    return true;
}
int main()
{
    int T;
    cin >> T;
    while (T--)
    {
        memset(e, 0, sizeof(e));
        int u, v, w;
        cin >> n >> m;
        for (int i = 0; i < m; i++)
        {
            cin >> u >> v >> w;
            e[u].push_back({v, w});
            if (w >= 0)
                e[v].push_back({u, w});
        }
        if (!spfa(n, 1))
            cout << "YES" << endl;
        else
            cout << "NO" << endl;
    }
    return 0;
}

P3385 [模板]负环

Johnson

#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
#include <vector>

using namespace std;
#define INF 1e9
const int MAXN = 30005;
int n, m;
struct edge
{
    int v, w;
};
struct node
{
    long long dis;
    int u; // 距离,点
    bool operator>(const node &a) const
    {
        return dis > a.dis;
    }
};
vector<edge> e[MAXN];
long long d[MAXN], cnt[MAXN], vis[MAXN], h[MAXN];

bool spfa(int s)
{
    queue<int> q;
    memset(h, 0x3f, sizeof(h));
    memset(cnt, 0, sizeof(cnt));
    memset(vis, 0, sizeof(vis));
    h[s] = 0, vis[s] = 1;
    q.push(s);
    while (!q.empty())
    {
        int u = q.front();
        q.pop();
        vis[u] = 0; // 出队后取消标记
        for (auto ed : e[u])
        {
            int v = ed.v, w = ed.w;
            if (h[v] > h[u] + w)
            {
                h[v] = h[u] + w;
                cnt[v] = cnt[u] + 1; // 最短路经过的边数
                if (cnt[v] > n)      // 最短路边数大于等于n显然有负环
                    return false;
                if (!vis[v])
                {
                    q.push(v);
                    vis[v] = 1;
                }
            }
        }
    }
    return true;
}

void dijkstra(int s)
{
    priority_queue<node, vector<node>, greater<node>> q; // q{dis,u}
    for (int i = 1; i <= n; i++)
        d[i] = INF; // 不能用memset
    memset(vis, 0, sizeof(vis));
    d[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 (d[v] > d[u] + w)
            {
                d[v] = d[u] + w;
                q.push({d[v], v});
            }
        }
    }
}
int main()
{
    cin >> n >> m;
    for (int i = 0; i < m; i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        e[a].push_back({b, c});
    }
    for (int i = 1; i <= n; i++)
        e[0].push_back({i, 0}); // 加虚拟源点0
    if (!spfa(0))
    {
        cout << -1 << endl;
        return 0;
    }
    for (int u = 1; u <= n; u++)
        for (auto &ed : e[u])
            ed.w += h[u] - h[ed.v]; // 改造边权,使其非负(三角形法则)
    for (int i = 1; i <= n; i++)
    {
        dijkstra(i);
        long long ans = 0;
        for (int j = 1; j <= n; j++)
        {
            if (d[j] == INF)
                ans += (long long)j * INF;
            else
                ans += (long long)j * (d[j] + h[j] - h[i]);
        }
        cout << ans << endl;
    }
    return 0;
}

P5905 [模板]全源最短路

posted @ 2025-07-05 20:12  张诗羽  阅读(10)  评论(0)    收藏  举报