Dijkstra's algorithm for finding the shortest path (super detailed) is constantly being updated

Dijkstra finds the shortest path


Shortest path problem

Insert picture description here
Let me talk about the plain version first

Dijkstra algorithm

The Dijkstra algorithm (Dijkstra) was proposed by the Dutch computer scientist Dijkstra in 1959, so it is also called the Dijkstra algorithm. It is the shortest path algorithm from one vertex to the other vertices, and it solves the shortest path problem in the right graph. The main feature of Dijkstra's algorithm is that it starts from the starting point and adopts the strategy of greedy algorithm. Each time it traverses to the adjacent node of the vertex that is closest to the starting point and has not been visited until it expands to the end point.

Let us first look at how to find the shortest distance from point 1 to point n.

Implementation process

Insert picture description here

Code
int Dijkstra()
{
    
    
    memset(dist,0x3f,sizeof dist);//除1号结点外,其他均初始为无穷大
    dist[1]=0;
    for(int i=0;i<n;i++) //n次迭代,每次寻找不在s中距离最近的点t
    {
    
    
        int t=-1;// 便于更新第一个点
        for(int j=1;j<=n;j++)
          if(!st[j]&&(t==-1||dist[j]<dist[t])) t=j;
        st[t]=true;  //将t加到s中
        for(int j=1;j<=n;j++)  //用t更新其他点的距离
          dist[j]=min(dist[j],dist[t]+g[t][j]);
    }
    if(dist[n]==0x3f3f3f3f) return -1; //路径不存在
    else return dist[n];
}

Next give the template
Naive dijkstra algorithm
time complexity is O(n^2+m), n represents the number of points, m represents the number of sides

int g[N][N];  // 存储每条边
int dist[N];  // 存储1号点到每个点的最短距离
bool st[N];   // 存储每个点的最短路是否已经确定

// 求1号点到n号点的最短路,如果不存在则返回-1
int dijkstra()
{
    
    
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;

    for (int i = 0; i < n - 1; i ++ )
    {
    
    
        int t = -1;     // 在还未确定最短路的点中,寻找距离最小的点
        for (int j = 1; j <= n; j ++ )
            if (!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;

        // 用t更新其他点的距离
        for (int j = 1; j <= n; j ++ )
            dist[j] = min(dist[j], dist[t] + g[t][j]);

        st[t] = true;
    }

    if (dist[n] == 0x3f3f3f3f) return -1;
    return dist[n];
}

Okay, let’s look at a template question. Practice is the only criterion for testing truth.

AcWing 849. Dijkstra finds the shortest path I

Given a directed graph with n points and m edges, there may be multiple edges and self-loops in the graph, and all edge weights are positive.
Please find the shortest distance from point 1 to point n. If you cannot walk from point 1 to point n, output -1.
Input format The
first line contains integers n and m.
Each of the next m rows contains three integers x, y, and z, indicating that there is a directed edge from point x to point y, and the length of the side is z.
Output format
Output an integer, representing the shortest distance from point 1 to point n.
If the path does not exist, -1 is output.
The data range is
1≤n≤500,
1≤m≤105,
and the length of the side involved in the figure does not exceed 10000.
Input sample:
3 3
1 2 2
2 3 1
1 3 4
Output sample:
3

Complete code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=510;
int g[N][N];    //稠密图用邻接矩阵存储比较节省空间
int dist[N];    //dist[i] i结点到起始点(1号结点)的距离
bool st[N] ;    //st[i] 用于标记i结点的最短路是否确定,若确定st[i]=true;
int n,m;
int Dijkstra()
{
    
    
    memset(dist,0x3f,sizeof dist);//除1号结点外,其他均初始为无穷大
    dist[1]=0;
    for(int i=0;i<n;i++) //n次迭代,每次寻找不在s中距离最近的点t
    {
    
    
        int t=-1;// 便于更新第一个点
        for(int j=1;j<=n;j++)
          if(!st[j]&&(t==-1||dist[j]<dist[t])) t=j;
        st[t]=true;  //将t加到s中
        for(int j=1;j<=n;j++)  //用t更新其他点的距离
          dist[j]=min(dist[j],dist[t]+g[t][j]);
    }
    if(dist[n]==0x3f3f3f3f) return -1; //路径不存在
    else return dist[n];
}
int main()
{
    
    
    scanf("%d%d",&n,&m);
    memset(g,0x3f,sizeof g);   //邻接矩阵的初始化,由于求的是最小值,因此初始为无穷大
    while(m--)
    {
    
    
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        g[x][y]=min(g[x][y],z); //重边中去取最小值
    }
    printf("%d\n",Dijkstra());
    return 0;
}

If you don’t understand something, don’t worry, then look down

FAQ Collection

  1. Why is 0x3f OK when assigning a value, memset(dist,0x3f,sizeof dist)but when it is verified later, it must be if(dist[n]==0x3f3f3f3f)but not the if(dist[n]==0x3f)
    answer :: It memsetis initialized by bytes, int contains 4 bytes, so the value after initialization is 0x3f3f3f3f.
  2. Why memset(dist,0x3f,sizeof dist)to initialize the
    answer: : 0x3f3f3f3f decimal is 1061109567, 1e9 is the level (magnitude and a 0x7fffffff, 0x7fffffff represents the maximum value of the 32-bit int), and the data in the general case is smaller than 1e9, so it It can be used as infinity without data being larger than infinity. On the other hand, since the general data is never greater than 10^9, when we add infinity to a data, it will not overflow (this satisfies "infinity plus a finite number is still infinity") , In fact 0x3f3f3f3f+0x3f3f3f3f=2122219134, this is very large but does not exceed the representation range of 32-bit int, so it 0x3f3f3f3falso meets our "infinity plus infinity or infinity" needs.
  3. for(int i=0;i<n;i++) { t=-1 }Why this tshould evaluate to -1
    answer: Because every time we find all points not yet determined the shortest distance, the distance to this point in the shortest point. t = - 1It is stset for the convenience of finding the first point in this set to update.
  4. If it is to ask how to change the shortest distance from a to b? (Good question)
    Answer: It will be used when initializing dist[a]=0, and when returning return dist[b].
  5. Do self-loops and double edges affect Dijkstrea's algorithm?
    Answer: The self-loop has no effect in the naive version of dijkstra's algorithm, so the weight of the self-loop can be any number, as long as it is not a negative number. For heavy edges, we take the minimum value of the heavy edges, which is the code g[x][y]=min(g[x][y],z).
  6. Why use an adjacency matrix for storage instead of an adjacency list?
    Answer: Whether we use the adjacency matrix or the adjacency list to represent the graph, we need to judge whether a graph is a sparse graph or a dense graph. A dense graph refers to the number of edges |E| close to |V|², and a sparse graph refers to the number of edges |E| is much smaller than |V|² (a lot of magnitude difference). This question is about dense graphs. Obviously, dense graphs are stored in adjacency matrix to save space, and vice versa.

Questions will be updated continuously, please leave a message in the comment area.

Guess you like

Origin blog.csdn.net/weixin_45629285/article/details/109406455