最短路

· · 算法·理论

SPFA

#include <iostream>
#include <vector>
#include <queue>
#define MAX 2147483647
using namespace std;

struct Node
{
    int v, dis;
};

vector <Node> a[10001];

int n, m, s, d[10001];
bool vis[10001];

void SPFA()
{
    queue <int> q;
    d[s] = 0;
    vis[s] = true;
    q.push(s);
    while(!q.empty())
    {
        int u = q.front(); q.pop();
        //cout << u << endl;
        vis[u] = false;
        for(int x = 0; x < a[u].size(); x++)
        {
            int v = a[u][x].v;
            //cout << "v: " << v << endl;
            if(d[v] > d[u] + a[u][x].dis)
            {
                d[v] = d[u] + a[u][x].dis;
                if(!vis[v])
                {
                    vis[v] = true;
                    q.push(v);
                }
            }
        }
    }
}

int main()
{
    cin >> n >> m >> s;
    for(int x = 1; x <= n; x++) d[x] = MAX;
    for(int x = 0; x < m; x++)
    {
        int u;
        Node tmp;
        cin >> u >> tmp.v >> tmp.dis;
        a[u].push_back(tmp);
    }
    SPFA();
    for(int x = 1; x <= n; x++) cout << d[x] << " ";
    cout << endl;
    return 0;
}

SPFA(判负环)

#include <bits/stdc++.h>
#define INF 0x7fffffff
#define MAXN 200010
#define LL long long
using namespace std;

struct node
{
    int v, w;
};

int n, m, d[MAXN], cnt[MAXN];
vector <node> g[MAXN];
bool vis[MAXN], findN;

void SPFA(int st)
{
    findN = false;
    for(int x = 0; x < n; x++) d[x] = INF;
    queue <int> q;
    q.push(st);
    d[st] = 0;
    vis[st] = true;
    cnt[st]++;
    while(!q.empty())
    {
        int u = q.front(); q.pop();
        vis[u] = false;
        for(int x = 0; x < g[u].size(); x++)
        {
            int v = g[u][x].v, w = g[u][x].w;
            if(d[u] != INF && d[u] + w < d[v])
            {
                d[v] = d[u] + w;
                if(!vis[v])
                {
                    q.push(v);
                    vis[v] = true;
                    cnt[v]++;
                    if(cnt[v] > n)
                    {
                        findN = true;
                        return;
                    }
                }
            }
        }
    }
}

int main()
{
    int st;
    cin >> n >> m >> st;
    for(int x = 1; x <= m; x++)
    {
        int u, v, w;
        cin >> u >> v >> w;
        g[u].push_back((node){v, w});
    }
    SPFA(st);
    if(findN)
    {
        cout << "NEGATIVE CYCLE" << endl;
        exit(0);
    }
    for(int x = 0; x < n; x++)
    {
        if(d[x] == INF) cout << "INF" << endl;
        else cout << d[x] << endl;
    }
    return 0;
}

SPFA(链式前向星)

#include <iostream>
#include <cstring>
#include <queue>
#define INF 0x7fffffff
#define MAXN 1000001
using namespace std;

struct Edge
{
    int to, next, w;
} e[MAXN];

int n, m, head[MAXN], cnt, d[MAXN];

void addEdge(int u, int v, int w)
{
    e[cnt].to = v;
    e[cnt].next = head[u];
    e[cnt].w = w;
    head[u] = cnt++;
}

void run(int i)
{
    d[i] = 0;
    queue <int> q;
    q.push(i);
    while(!q.empty())
    {
        int u = q.front(); q.pop();
        for(int x = head[u]; x >= 0; x = e[x].next)
        {
            int v = e[x].to, w = e[x].w;
            if(d[u] + w < d[v])
            {
                d[v] = d[u] + w;
                q.push(v);
            }
        }
    }
}

int main()
{
    int s;
    memset(head, -1 ,sizeof(head));
    cin >> n >> m >> s;
    for(int x = 1; x <= n; x++) d[x] = INF;
    for(int x = 0; x < m; x++)
    {
        int u, v, w;
        cin >> u >> v >> w;
        addEdge(u, v, w);
        //addEdge(v, u);
    }
    run(s);
    for(int x = 1; x <= n; x++) cout << d[x] << " ";
    cout << endl;
    return 0;
}

Dijkstra(基础)

#include <iostream>
#include <vector>
#define MAX 2147483647
using namespace std;

struct Node
{
    int v, dis;
};

vector <Node> a[100001];
int n, m, s, d[100001];
bool vis[100001];

void Dijkstra()
{
    for(int x = 1; x <= n; x++) d[x] = MAX;
    d[s] = 0;
    for(int x = 1; x <= n; x++)
    {
        int minn = -1, min = MAX;
        for(int y = 1; y <= n; y++)
        {
            if(vis[y] == false && d[y] < min)
            {
                min = d[y];
                minn = y;
            }
        }
        //cout << minn << endl;
        if(minn == -1) return;
        vis[minn] = true;
        for(int y = 0; y < a[minn].size(); y++)
        {
            int v = a[minn][y].v;
            //cout << v << endl;
            if(vis[v] == false && d[minn] + a[minn][y].dis < d[v])
                d[v] = d[minn] + a[minn][y].dis;
        }
    }
}

int main()
{
    cin >> n >> m >> s;
    for(int x = 0; x < m; x++)
    {
        Node tmp;
        int u;
        cin >> u >> tmp.v >> tmp.dis;
        a[u].push_back(tmp);
    }
    Dijkstra();
    for(int x = 1; x <= n; x++) cout << d[x] << " ";
    cout << endl;
    return 0;
}

Dijkstra(小根堆优化)

#include <iostream>
#include <vector>
#include <queue>
#define MAX 2147483647
using namespace std;

struct Node
{
    int v, dis;
};

struct pri
{
    int ans, id;
    bool operator < (const pri &x) const{return x.ans < ans;}
};

priority_queue <pri> q;
vector <Node> a[100001];
int n, m, s, d[100001];
bool vis[100001];

void Dijkstra()
{
    for(int x = 1; x <= n; x++) d[x] = MAX;
    d[s] = 0;

    q.push((pri){0, s});
    while(!q.empty())
    {
        pri tmp = q.top();
        q.pop();
        int minn = tmp.id;
        if(!vis[minn])
        {
            vis[minn] = true;
            for(int y = 0; y < a[minn].size(); y++)
            {
                int v = a[minn][y].v;
                //cout << v << endl;
                if(vis[v] == false && d[minn] + a[minn][y].dis < d[v])
                {
                    d[v] = d[minn] + a[minn][y].dis;
                    if(!vis[v]) q.push((pri){d[v], v});
                }
            }
        }
    }
}

int main()
{
    cin >> n >> m >> s;
    for(int x = 0; x < m; x++)
    {
        Node tmp;
        int u;
        cin >> u >> tmp.v >> tmp.dis;
        a[u].push_back(tmp);
    }
    Dijkstra();
    for(int x = 1; x <= n; x++) cout << d[x] << " ";
    cout << endl;
    return 0;
}

Floyd

多源最短路

#include <bits/stdc++.h>
#define INF 0x7fffffff
#define MAXN 210
typedef long long LL;
using namespace std;

int n, m;
int d[MAXN][MAXN];
bool findN;

void Floyd()
{
    findN = false;
    for(int z = 0; z < n; z++)
        for(int x = 0; x < n; x++)
            for(int y = 0; y < n; y++)
                if(d[x][z] < INF && d[z][y] < INF)
                    d[x][y] = min(d[x][y], d[x][z] + d[z][y]);
    for(int x = 0; x < n; x++)
        if(d[x][x] < 0) findN = true;
}

int main()
{
    cin >> n >> m;
    for(int x = 0; x < n; x++)
        for(int y = 0; y < n; y++)
            d[x][y] = (x == y ? 0 : INF);

    for(int x = 1; x <= m; x++)
    {
        int u, v, w;
        cin >> u >> v >> w;
        d[u][v] = min(d[u][v], w);
    }
    Floyd();
    if(findN)
    {
        cout << "NEGATIVE CYCLE" << endl;
        exit(0);
    }
    for(int x = 0; x < n; x++)
    {
        for(int y = 0; y < n-1; y++)
            if(d[x][y] == INF) cout << "INF" << " ";
            else cout << d[x][y] << " ";

        if(d[x][n-1] == INF) cout << "INF" << endl;
        else cout << d[x][n-1] << endl;
    }
    return 0;
}