Dijkstra of the shortest path of graph -- pseudo code, complete implementation code (adjacency matrix, adjacency table), examples and problem points

Keywords: REST less

1 Dijkstra (single source shortest path problem)

1.1 minimum distance

1.1.1 pseudo code

//Figure G is generally set as a global variable; Array d is the shortest path length from the source point to each point, and s is the starting point
Dijkstra(G, d[], s){
    Initialization
    for (n cycles)
    {
        U = the label of the vertex that makes d[u] the smallest but has not been accessed; 
        u has been visited;
        for (all vertices V that can be reached from u)
        {
            if(v is not accessed & & taking u as the intermediary point makes the shortest path d[v] from s to V better){
                Optimize d[v];
            }
        }
    }
}

1.1.2 adjacency matrix

  • For small points (no more than 1000)
  • Time complexity
    • Outer loop O(V) [V is the number of vertices] and inner loop (O(V) is needed to find the smallest d[u], O(V) is needed to enumerate V, and the total time complexity is O(V * (V + V)) = O(V2)
const int MAXV = 1000;//max vertex 
const int INF = 0x3fffffff;
int G[MAXV][MAXV], n;//Number of graphs and vertices
int d[MAXV];//The shortest path from the starting point to each point
bool vis[MAXV] = {false};//Whether the tag is accessed

void Dijkstra(int s){//s starting point
    fill(d, d + MAXV, INF);//Assign the entire array d to INDF, which is not reachable
    d[s] = 0;//The distance from the starting point to itself is 0
    for (int i = 0; i < n; ++i)//Circular c times
    {
        int u = - 1, min = INF;//U makes d[u] minimum, MIN stores the minimum d[u]
            for (int j = 0; j < n; ++j)//Find the smallest d [] of the unreachable vertices
            {
                if(vis[j] == false && d[j] < min){
                    u = j;
                    min = d[j];
                }
            }

            //No d[u] less than INF can be found, indicating that the remaining vertices are not connected to the starting point s
            if(u == -1) return;
            vis[u] = true;//Tag u has been accessed
            for (int v = 0; v < n; ++v)
            {
                //If V is not accessed & & u can reach V & & make u as the intermediary point can make d[v] better
                if(vis[v] == false && G[u][v] != INF && d[u] + G[u][v] < d[v]){
                    d[v] = d[u] + G[u][v];//Optimizing d[v]
                }
            }
    }
}

1.1.3 adjacency table

  • Time complexity
    • Outer loop O(V) [V is the number of vertices] and inner loop (finding the smallest d[u] requires O(V), enumerating V requires O(adj[u].size()), the total number of enumerating V is O(∑ u=0n − 1adj [u]. Size() \ sum {u = 0} ^ {n-1} adj [u]. Size() ∑ u=0n − 1 adj[u].size()) = O(E), and the total time complexity is O(V2 + E)
struct node
{
    int v;//Target vertex of edge
    int dis;//Border rights
};

const int MAXV = 1000;//max vertex 
const int INF = 0x3fffffff;
vector<node> Adj[MAXV];/// / adjacency list
int n;//Vertex number
int d[MAXV];//The shortest path from the starting point to each point
bool vis[MAXV] = {false};//Whether the tag is accessed

void Dijkstra(int s){//s starting point
    fill(d, d + MAXV, INF);//Assign the entire array d to INDF, which is not reachable
    d[s] = 0;//The distance from the starting point to itself is 0
    for (int i = 0; i < n; ++i)//Circular c times
    {
        int u = - 1, min = INF;//U makes d[u] minimum, MIN stores the minimum d[u]
            for (int j = 0; j < n; ++j)//Find the smallest d [] of the unreachable vertices
            {
                if(vis[j] == false && d[j] < min){
                    u = j;
                    min = d[j];
                }
            }

            //No d[u] less than INF can be found, indicating that the remaining vertices are not connected to the starting point s
            if(u == -1) return;
            vis[u] = true;//Tag u has been accessed
            for (int j = 0; j < Adj[u].size(); ++j)
            {
                int v = Adj[u][j].v;//The vertex v that u can reach can be obtained directly by adjacency table
                if(vis[v] == false && d[u] + Adj[u][j].dis < d[v]){
                    //V is not accessed & & using u as a mediation point can make d[v] better
                    d[v] = d[u] + Adj[u][j].dis;//Optimizing d[v]
                }
            }
    }
}

1.1.4 optimization and points for attention

  • optimization
    • The time complexity of the above two algorithms is O(V2). Since each vertex must be marked as accessed, the O(V) of the outer loop cannot be avoided, but the one looking for the smallest d[u] can not reach the length of O(V). Heap optimization can be used to reduce the complexity. The simplest way to write is to directly use the priority queue of STL, so that the time of adjacent table can be reduced Inter complexity reduced to O(VlogV+E)
  • Be careful
    • If we want undirected edge, we only regard undirected edge as two opposite directed edges.

1.1.5 example

  • Problem Description:
    Input Specification:
    Each input file contains one test case. For each case, the first line contains three positive integer n(<=1000), m , s, which are the number of nodes, the number of edge, and start of nodes.Then m lines follow, each describes each edge by 3 integers, which are starting node, ending node, and weight of node.

Output Specification:
output in a line the number of nodes distance which from starting node to each nodes .

Sample Input:
6 8 0
0 1 1
0 3 4
0 4 4
1 3 2
2 5 1
3 2 2
3 4 3
4 5 3
Sample Output:
0 1 5 3 4 6 
  • Solution code
#include <cstdio>
#include <algorithm>

using std::fill;

const int MAXV  = 1000;
const int INF = 0x3fffffff;
int G[MAXV][MAXV];
bool vis[MAXV] = {false};
int d[MAXV];
int n, m, s;

void Dijkstra(int s){
    fill(d, d + MAXV, INF);
    d[s] = 0;
    for (int i = 0; i < n; ++i)
    {
        int u = -1, min = INF;
        for (int j = 0; j < n; ++j)
        {
            if(vis[j] == false && d[j] < min){
                u = j;
                min = d[j];
            }
        }

        if(u == -1) return;

        vis[u] = true;

        for (int v = 0; v < n; ++v)
        {
            if(vis[v] == false && G[u][v] != INF && d[u] + G[u][v] < d[v]){
                d[v] = d[u] + G[u][v];
            }
        }
    }
}

int main(int argc, char const *argv[])
{
    int u, v ,w;
    scanf("%d%d%d", &n, &m, &s);//Vertex number, edge number, start number

    fill(G[0], G[0] + MAXV * MAXV, INF);//Initialization diagram G

    for (int i = 0; i < m; ++i)
    {
        scanf("%d%d%d", &u, &v, &w);//Input the edge weight of u, v and U - > v
        G[u][v] = w;
    }

    Dijkstra(s);

    for (int i = 0; i < n; ++i)
    {
        printf("%d ", d[i]);
    }
    return 0;
}
/*
6 8 0
0 1 1
0 3 4
0 4 4
1 3 2
2 5 1
3 2 2
3 4 3
4 5 3
*/

1.2 shortest path

1.2.1 pseudo code

//Figure G is generally set as a global variable; Array d is the shortest path length from the source point to each point, and s is the starting point
Dijkstra(G, d[], s){
    Initialization
    for (n cycles)
    {
        U = the label of the vertex that makes d[u] the smallest but has not been accessed; 
        u has been visited;
        for (all vertices V that can be reached from u)
        {
            if(v is not accessed & & taking u as the intermediary point makes the shortest path d[v] from s to V better){
                Optimize d[v];
                Let the precursor of v be u;
            }
        }
    }
}

1.2.2 adjacency matrix

const int MAXV = 1000;
const int INF = 0x3ffffff;
int G[MAXV][MAXV], n;
bool vis[MAXV] = {false};
int pre[MAXV];
int d[MAXV];

void Dijkstra(int s){//Find the precursor of each node in the shortest path
    fill(d, d + MAXV, INF);

    for (int i = 0; i < n; ++i)//Newly added
    {
        pre[i] = i;//The precursor of each node in the initial state is itself
    }

    for (int i = 0; i < n; ++i)
    {
        int u = -1, min = INF;
        for (int j = 0; j < n; ++j)
        {
            if(vis[j] == false && d[j] <min){
                u = j;
                min = d[j];
            }
        }

        if(u == -1) return;
        vis[u] = true;
        for (int v = 0; v < n; ++v)
        {
            if(vis[v] == false && G[u][v] != INF && d[u] + G[u][v] < d[v]){
                d[v] = d[u] + G[u][v];
                pre[v] = u;
            }
        }
    }
}

void DFS(int s, int v){//s: Start point number; v: currently accessed vertex number (recursion from end point)
    if(v == s){
        printf("%d\n", s);
        return;
    }

    DFS(s, pre[v]);//Recursive access to the precursor node of V pre[v]
    printf("%d\n", v);//After return ing from the deepest point, output the vertex number of each layer
}

1.2.3 adjacency table

struct node
{
    int v;
    int dis;
};

const int MAXV = 1000;
const int INF = 0x3ffffff;
vector<node> Adj[MAXV];/// / adjacency list
int n;
bool vis[MAXV] = {false};
int pre[MAXV];
int d[MAXV];

void Dijkstra(int s){//Find the precursor of each node on the shortest path
    fill(d, d + MAXV, INF);

    for (int i = 0; i < n; ++i)//Newly added
    {
        pre[i] = i;//The precursor of each node in the initial state is itself
    }

    for (int i = 0; i < n; ++i)
    {
        int u = -1, min = INF;
        for (int j = 0; j < n; ++j)
        {
            if(vis[j] == false && d[j] <min){
                u = j;
                min = d[j];
            }
        }

        if(u == -1) return;
        vis[u] = true;
        for (int j = 0; j < Adj[u].size(); ++j)
        {
            int v = Adj[u][j].v;
            if(vis[v] == false && d[u] + Adj[u][j].dis < d[v]){
                d[v] = d[u] + Adj[u][j].v;
                pre[v] = u;
            }
        }
    }
}

void DFS(int s, int v){//s: Start point number; v: currently accessed vertex number (recursion from end point)
    if(v == s){
        printf("%d\n", s);
        return;
    }

    DFS(s, pre[v]);//Recursive access to the precursor node of V pre[v]
    printf("%d\n", v);//After return ing from the deepest point, output the vertex number of each layer
}

1.3 related applications

When there is more than one shortest path from the starting point to the end point, the topic will give the second scale (the first scale is the distance), and it is required to select the best one of the second scale from all the shortest paths. The second scale is commonly used in the following three methods or combinations:

  • 1 new edge right
    The cost of U - > V is represented by cost[u][v], and an array c [] is added. The minimum cost from the starting point s to the vertex u is c[u]. When initializing, c[s] is 0, and the rest c[u] is INF.
for (int v = 0; v < n; ++v)
{
    //If v is not accessed & & u can reach v
    if(vis[v] == false && G[u][v] != INF){
        if(d[u] + G[u][v] < d[v]){//Taking u as the intermediary point can make d[v] better
            d[v] = d[u] + G[u][v];
            c[v] = c[u] + cost[u][v];
        }else if(d[u] + G[u][v] == d[v] && cost[u] + cost[u][v] < cost[v]){
            c[v] = c[u] + cost[u][v];//Whether the shortest distance can make c[v] better
        }
    }
}
  • 2. New rights
    Take the newly added point weight as an example to represent the materials that can be collected in the city, use weight[u] as the number of materials in the city u (input by the title), and add an array w [], so that the maximum materials that can be collected from the starting point s to the vertex u are w[u], only w[s] and the rest w[u] are 0 when initializing.
for (int v = 0; v < n; ++v)
{
    //If v is not accessed & & u can reach v
    if(vis[v] == false && G[u][v] != INF){
        if(d[u] + G[u][v] < d[v]){//Taking u as the intermediate point can make d[v] better
            d[v] = d[u] + G[u][v];
            w[v] = w[u] + weight[u][v];
        }else if(d[u] + G[u][v] == d[v] && w[u] + weight[v] > w[v]){
            w[v] = w[u] + weight[v];//Whether the shortest distance can make w[v] better
        }
    }
}

  • 3 find the shortest path.
    Just add an array num [] to make the shortest path from the starting point s to the vertex u be num[u]. During initialization, only num[s] is 1, and the rest num[u] is 0.
for (int v = 0; v < n; ++v)
{
    //If v is not accessed & & u can reach v
    if(vis[v] == false && G[u][v] != INF){
        if(d[u] + G[u][v] < d[v]){//Taking u as the intermediate point can make d[v] better
            d[v] = d[u] + G[u][v];
            num[v] = num[u];
        }else if(d[u] + G[u][v] == d[v]){
            num[v] += um[u];//Whether the shortest distance can make w[v] better
        }
    }
}
336 original articles published, 51 praised, 40000 visitors+
Private letter follow

Posted by tisa on Sat, 15 Feb 2020 19:36:13 -0800