Shortest path algorithm template (Dijkstra, Bellman_ford, spfa, Floyd)

Summary of shortest path algorithm templates

In graph theory, the graph is directed and undirected, and only the algorithm of the directed graph is considered here. For undirected graphs, we see them as a special kind of directed graph, for all undirected edges u ↔ v u \leftrightarrow v u ↔ v is considered yes u → v u\to v u_v and v → u v \to u v→u.

Appointment: n n n represents the number of points in the graph. m m m represents the number of edges in the graph.

Density Map: m m m and n 2 n^2 n2 orders of magnitude are roughly the same

Sparse graph: m m m and n n n orders of magnitude are roughly the same

Mapping

There are two general ways of drawing:

  1. Adjacency Matrix: Define a two-dimensional array g [ N ] [ N ] g[N][N] g[N][N], g [ i ] [ j ] g[i][j] g[i][j] represents a point i i i and j j Edge weight between j.
  2. Adjacency table: An array of analogue adjacency tables with a single-chain table for each node that stores all the adjacent edges of the point.

Special, for Bellman_ For the Ford algorithm, we usually define an array of structs to store information for all edges.

Shortest path algorithm

Shortest path algorithms are generally divided into two categories:

  1. Single-source shortest path, common algorithms are:

    ( 1 ) (1) (1)Dijkstra: only if all edges have positive edge weights can be used, algorithm time complexity in dense graph by O ( n 2 ) For O(n^2) Is O(n2), and the algorithm time complexity in the sparse graph is m l o n g ( n ) mlong(n) mlong(n).

    ( 2 ) (2) (2)Bellman_ford: use when there are negative weighted edges, shortest path problem with limit on number of edges, shortest path problem when there are negative weighted circuits, time complexity is O ( n m ) O(nm) O(nm).

    ( 3 ) (3) (3)spfa - Bellman_for queue optimization Ford algorithm: time complexity is O ( m ) O(m) O(m), the worst time complexity is O ( n m ) O(nm) O(nm).

  2. Multi-source shortest path:

    ( 1 ) (1) (1) Floyd: Standard Freud algorithm, triple loop. After the cycle ends d [ i ] [ j ] d[i][j] d[i][j] stores points i i i-to-point j j The shortest distance of j. It is important to note that the order of loops does not change: the first layer enumerates the middle points, and the second and third layers enumerate the starting and ending points. Time Complexity O ( n 3 ) O(n^3) O(n3).

Dijkstra algorithm template (including heap optimization)

Austere Dijkstra

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 510, INF = 0x3f3f3f3f;

int n, m;
int g[N][N];
int dist[N];
bool st[N]; // Determine the set of shortest paths

void dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    
    for(int i = 0; i < n; i ++)
    {
        int t = -1;
        for(int j = 1; j <= n; j ++) // Find the minimum distance to update other points
            if(!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;
        
        // Update Other Points
        for(int j = 1; j <= n; j ++)
            dist[j] = min(dist[j], dist[t] + g[t][j]);
        
        // Mark the point that has the shortest path determined
        st[t] = true;
    } 
}

int main()
{
    cin >> n >> m;
    
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= n; j ++)
            if(i == j) g[i][j] = 0;
            else g[i][j] = INF;
            
    while (m -- )
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        g[a][b] = min(g[a][b], c);
    }
    
    dijkstra();
    
    if(dist[n] == INF) puts("-1");
    else printf("%d\n", dist[n]);
    
    return 0;
}

Heap optimized version dijkstra

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

using namespace std;

const int N = 150010, INF = 0x3f3f3f3f;

typedef pair<int, int> PII;

int n, m;
int h[N], e[N], ne[N], w[N], idx;
int dist[N];
bool st[N]; // Set of points to determine the shortest path

void add(int a, int b, int c)
{ 
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++;
}

void dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    
    dist[1] = 0;
    priority_queue<PII, vector<PII>, greater<PII>> heap;
    heap.push({0, 1});
    
    while(heap.size())
    {
        auto t = heap.top();
        heap.pop();
        
        int ver = t.second;
        
        if(st[ver]) continue;
        st[ver] = true;
        
        for(int i = h[ver]; i != -1; i = ne[i])
        {
            int j = e[i];
            if(dist[j] > dist[ver] + w[i])// Replace adjacent edges when their distance is greater than the distance updated with the current point
            {
                dist[j] = dist[ver] + w[i];// d[ver] is the current minimum point distance; w[i] is the weight of the current adjacent edge
                heap.push({dist[j], j});
            }
        }
    }
}

int main()
{
    cin >> n >> m;
    
    memset(h, -1, sizeof h);
    
    while(m --)
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c);
    }
    
    dijkstra();
    
    if(dist[n] == INF) puts("-1");
    else printf("%d\n", dist[n]);
    
    return 0;
}

Bellman_Ford algorithm template

Bellman_Ford

Bellman_must be selected to solve the shortest path problem with a limited number of edges Ford

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 510, M = 10010, INF = 0x3f3f3f3f;

struct Edge
{
    int a, b, w;
}edges[M];

int n, m, k;
int dist[N], backup[N];

void Bellman_Ford()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    
    for(int i = 0; i < k; i ++)
    {
        memcpy(backup, dist, sizeof dist);
        for(int j = 0; j < m; j ++)
        {
            int a = edges[j].a, b = edges[j].b, w = edges[j].w;
            dist[b] = min(dist[b], backup[a] + w);
        }
    }
}

int main()
{
    cin >> n >> m >> k;
    
    for(int i = 0; i < m; i ++)
    {
        int a, b, w;
        scanf("%d%d%d", &a, &b, &w);
        edges[i] = {a, b, w};
    }
    
    Bellman_Ford();
    
    if(dist[n] > INF / 2) puts("impossible");
    else printf("%d\n", dist[n]);
    
    return 0;
}

spfa (Queue Optimized Bellman_Ford) algorithm template

spfa algorithm for shortest path

The spfa algorithm is similar to the heap-optimized Dijkstra algorithm in that it is very fast in general

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

using namespace std;

const int N = 100010, INF = 0x3f3f3f3f;

int n, m;
int h[N], e[N], ne[N], w[N], idx;
int dist[N];
bool st[N];

void add(int a, int b, int c)
{
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++;
}

void spfa()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    
    queue<int> q;
    q.push(1);
    st[1] = true;
    
    while(q.size())
    {
        int t = q.front();
        q.pop();
        
        st[t] = false;
        
        for(int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];
            if(dist[j] > dist[t] + w[i])
            {
                dist[j] = dist[t] + w[i];
                if(!st[j])
                {
                    st[j] = true;
                    q.push(j);
                }
            }
        }
    }
}

int main()
{
    cin >> n >> m;
    
    memset(h, -1, sizeof h);
    
    while (m -- )
    {
        int a, b, w;
        scanf("%d%d%d", &a, &b, &w);
        add(a, b, w);
    }
    
    spfa();
    
    if(dist[n] > INF / 2) puts("impossible");
    else printf("%d\n", dist[n]);
    
    return 0;
}

Floyd algorithm template

Floyd algorithm template questions

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 210, INF = 0x3f3f3f3f;

int g[N][N];
int n, m, Q;

void floyd()
{
    for(int k = 1; k <= n; k ++)
        for(int i = 1; i <= n; i ++)
            for(int j = 1; j <= n; j ++)
                g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
}

int main()
{
    scanf("%d%d%d", &n, &m, &Q);
    
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= n; j ++)
            if(i == j) g[i][j] = 0;
            else g[i][j] = INF;
            
    while(m --)
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        g[a][b] = min(g[a][b], c);
    }
    
    floyd();
    
    while(Q --)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        if(g[x][y] > INF / 2) puts("impossible");
        else printf("%d\n", g[x][y]);
    }
    
    return 0;
}

Keywords: C++ Algorithm data structure Graph Theory

Added by cougar23 on Sun, 13 Feb 2022 20:04:49 +0200