Shortest Path Algorithms (Rotation)

Posted by xmarcusx on Mon, 15 Jul 2019 21:31:40 +0200

The shortest path problem aims to find the shortest path between two nodes in the graph. There are four commonly used algorithms. Note whether the graph is undirected or directed

Dijkstra's
1 Dijkstra's algorithm solves the shortest path from a single source point to another vertex in the graph. It can only solve the problem of non-negative weight
2 Dijkstral can only find the shortest distance between any point and the source point (it can not find the shortest distance between any two points). It is also applicable to digraphs and undirected graphs with O(n^2) complexity.
3. The process of the algorithm:
1. Set the vertex set S and continue to make greedy choices to expand the set. A vertex belongs to set S if and only if the shortest path length from the source point to that point is known.
2 Initially, S contains only sources. Let U be a vertex of G. The path from source to U and only passing through the vertex of S in the middle is called a special path from source to U, and the shortest special path corresponding to each current vertex is distanced by dis array.
The 3D ijkstra algorithm extracts the vertex u with the shortest special length from V-S each time, adds u to S, and modifies the dis array. Once S contains all the vertices in V, the dis array records the shortest path length from the source point to other vertices.
4 Templates:
Without optimization, time complexity o(n^2)
  1. #define MAXN 1010   
  2. #define INF 0xFFFFFFF   
  3. int  value[MAXN][MAXN];/*Save the edge weights.*/  
  4. int  dis[MAXN];/*Save the shortest path between the source point and any point*/  
  5. int  father[MAXN];/*Father node that saves point i*/  
  6. int  vis[MAXN];/*Does the record vertex have not been taken?*/   
  7.   
  8. void input(){       
  9.       int star , end , v;  
  10.       scanf("%d%d" , &n , &m);  
  11.       /*Initialize the value array*/  
  12.      for(int i = 1 ; i <= n ; i++){  
  13.          for(int j = 1; j <= n ; j++)  
  14.              value[i][j] = INF;  
  15.      }  
  16.     for(int i = 0 ; i < m ; i++){  
  17.         scanf("%d%d%d" ,  &star , &end , &v);  
  18.         if(value[star][end] == INF)  
  19.             value[star][end] = value[end][star] = v;/*Processing into undirected graph*/  
  20.         else{  
  21.             if(v < value[star][end])/*Judging whether a double edge appears*/  
  22.                  value[star][end] = value[end][star] = v;  
  23.         }  
  24. }  
  25.   
  26. void dijkstra(int s){  
  27.      memset(vis , 0 , sizeof(vis));  
  28.      memset(father , 0 , sizeof(father));  
  29.      /*Initialize dis array*/  
  30.      for(int i = 1 ; i<= n ; i++)  
  31.           dis[i] = INF;  
  32.      dis[s] = 0;  
  33.      for(int i = 1 ; i <= n ; i++){/*Enumeration of n vertices*/  
  34.         int pos;  
  35.         pos = -1;  
  36.         for(int j = 1 ; j <= n ;j++){/*Find the shortest path to an unjoined set*/  
  37.            if(!vis[j] && (pos == -1 || dis[j] < dis[pos]))  
  38.               pos = j;  
  39.         }  
  40.         vis[pos] = 1;/*Add this point to the shortest path set*/  
  41.         for(int j = 1 ; j <= n ; j++){/*Update dis array*/  
  42.            if(!vis[j] && (dis[j] > dis[pos] + value[pos][j])){  
  43.              dis[j] = dis[pos] + value[pos][j];  
  44.              father[j] = pos;  
  45.            }  
  46.         }  
  47.      }  
  48. }  
  1. #define MAXN 1010  
  2. #define INF 0xFFFFFFF  
  3. int  value[MAXN][MAXN];/*Save the edge weights.*/  
  4. int  dis[MAXN];/*Save the shortest path between the source point and any point*/  
  5. int  father[MAXN];/*Father node that saves point i*/  
  6. int  vis[MAXN];/*Does the record vertex have not been taken?*/   
  7.   
  8. void input(){       
  9.       int star , end , v;  
  10.       scanf("%d%d" , &n , &m);  
  11.       /*Initialize the value array*/  
  12.      for(int i = 1 ; i <= n ; i++){  
  13.          for(int j = 1; j <= n ; j++)  
  14.              value[i][j] = INF;  
  15.      }  
  16.     for(int i = 0 ; i < m ; i++){  
  17.         scanf("%d%d%d" ,  &star , &end , &v);  
  18.         if(value[star][end] == INF)  
  19.             value[star][end] = value[end][star] = v;/*Processing into undirected graph*/  
  20.         else{  
  21.             if(v < value[star][end])/*Judging whether a double edge appears*/  
  22.                  value[star][end] = value[end][star] = v;  
  23.         }  
  24. }  
  25.   
  26. void dijkstra(int s){  
  27.      memset(vis , 0 , sizeof(vis));  
  28.      memset(father , 0 , sizeof(father));  
  29.      /*Initialize dis array*/  
  30.      for(int i = 1 ; i<= n ; i++)  
  31.           dis[i] = INF;  
  32.      dis[s] = 0;  
  33.      for(int i = 1 ; i <= n ; i++){/*Enumeration of n vertices*/  
  34.         int pos;  
  35.         pos = -1;  
  36.         for(int j = 1 ; j <= n ;j++){/*Find the shortest path to an unjoined set*/  
  37.            if(!vis[j] && (pos == -1 || dis[j] < dis[pos]))  
  38.               pos = j;  
  39.         }  
  40.         vis[pos] = 1;/*Add this point to the shortest path set*/  
  41.         for(int j = 1 ; j <= n ; j++){/*Update dis array*/  
  42.            if(!vis[j] && (dis[j] > dis[pos] + value[pos][j])){  
  43.              dis[j] = dis[pos] + value[pos][j];  
  44.              father[j] = pos;  
  45.            }  
  46.         }  
  47.      }  
  48. }  


  1. Optimized, time complexity is o(mlogn);  
  2. /*Using Adjacency Table to Optimize*/  
  3. #include<utility>    
  4. typedef pair<int , int>pii;/*pair Specifically bundled together two types*/  
  5. priority_queue<pii,vector<pii>,greater<pii> >q;/*Priority queues use "<" by defau lt, so the elements of priority queues are from large to small, so we define ">" comparison, STL can use greater < int > to express ">", so we can declare a small integer first-out priority queue.*/  
  6. #define MAXN 1010   
  7. #define INF 0xFFFFFFF   
  8. int n , m;/*There are n points and m edges.*/  
  9. int first[MAXN] , next[MAXN];/*first The array holds the first edge of node i, and next holds the next edge of edge e.*/  
  10. int u[MAXN] , v[MAXN] , value[MAXN];  
  11. int vis[MAXN];  
  12. int dis[MAXN];  
  13.   
  14. /*Read in this diagram*/  
  15. void input(){  
  16.      scanf("%d%d" , &n , &m);  
  17.      /*Initialize the header*/  
  18.      for(int i = 1 ; i <= n ; i++)  
  19.         first[i] = -1;  
  20.      for(int i = 1 ; i <= m ; i++){  
  21.         scanf("%d%d" , &u[i] , &v[i] , &value[i]);         
  22.         next[i] = first[u[i]];/*Head moving backwards*/  
  23.         first[u[i]] = i;/*Update table headers*/  
  24.      }  
  25. }  
  26.   
  27. /*Dijkstra*/  
  28. void Dijkstra(int s){  
  29.      memset(vis , 0 , sizeof(vis));  
  30.      /*Distance of Initiation Point*/  
  31.      for(int i = 1 ; i <= n ; i++)  
  32.           dis[i] = INF;  
  33.     dis[s] = 0;  
  34.      while(!q.empty())  
  35.         q.pop();  
  36.      q.push(make_pair(dis[s] , s));  
  37.      while(!q.empty()){  
  38.           pii u = q.top();  
  39.           q.pop();  
  40.           int x = u.second;  
  41.           if(vis[x])  
  42.             continue;   
  43.           vis[x] = 1;  
  44.           for(int i = first[x] ; i != -1 ; i = next[i]){  
  45.              if(dis[v[e]] > dis[x] + value[i]){  
  46.                 dis[v[i]] = dis[x] + value[i];  
  47.                 q.push(make_pair(dis[v[i] , v[i]));  
  48.              }  
  49.           }  
  50.      }  
  51. }  
  1. Optimized, time complexity is o(mlogn);  
  2. /*Using Adjacency Table to Optimize*/  
  3. #include<utility>   
  4. typedef pair<int , int>pii;/*pair Specifically bundled together two types*/  
  5. priority_queue<pii,vector<pii>,greater<pii> >q;/*Priority queues use "<" by defau lt, so the elements of priority queues are from large to small, so we define ">" comparison, STL can use greater < int > to express ">", so we can declare a small integer first-out priority queue.*/  
  6. #define MAXN 1010  
  7. #define INF 0xFFFFFFF  
  8. int n , m;/*There are n points and m edges.*/  
  9. int first[MAXN] , next[MAXN];/*first The array holds the first edge of node i, and next holds the next edge of edge e.*/  
  10. int u[MAXN] , v[MAXN] , value[MAXN];  
  11. int vis[MAXN];  
  12. int dis[MAXN];  
  13.   
  14. /*Read in this diagram*/  
  15. void input(){  
  16.      scanf("%d%d" , &n , &m);  
  17.      /*Initialize the header*/  
  18.      for(int i = 1 ; i <= n ; i++)  
  19.         first[i] = -1;  
  20.      for(int i = 1 ; i <= m ; i++){  
  21.         scanf("%d%d" , &u[i] , &v[i] , &value[i]);         
  22.         next[i] = first[u[i]];/*Head moving backwards*/  
  23.         first[u[i]] = i;/*Update table headers*/  
  24.      }  
  25. }  
  26.   
  27. /*Dijkstra*/  
  28. void Dijkstra(int s){  
  29.      memset(vis , 0 , sizeof(vis));  
  30.      /*Distance of Initiation Point*/  
  31.      for(int i = 1 ; i <= n ; i++)  
  32.           dis[i] = INF;  
  33.     dis[s] = 0;  
  34.      while(!q.empty())  
  35.         q.pop();  
  36.      q.push(make_pair(dis[s] , s));  
  37.      while(!q.empty()){  
  38.           pii u = q.top();  
  39.           q.pop();  
  40.           int x = u.second;  
  41.           if(vis[x])  
  42.             continue;   
  43.           vis[x] = 1;  
  44.           for(int i = first[x] ; i != -1 ; i = next[i]){  
  45.              if(dis[v[e]] > dis[x] + value[i]){  
  46.                 dis[v[i]] = dis[x] + value[i];  
  47.                 q.push(make_pair(dis[v[i] , v[i]));  
  48.              }  
  49.           }  
  50.      }  
  51. }  


Floyd (non-negative weight) is suitable for digraphs and undirected graphs

The idea of 1 floyd is to update the shortest distance by enumerating n points and using the idea of DP. Assuming that the current enumeration reaches the k-th point, there are two arbitrary points I and J. If the K is connected by j k, then we can know that dis [i] [j] = min (dis [i] [j], dis [i] [k] + dis [k] [j]; so long as n points are enumerated. Point, that means that the shortest path between all two points has been completely updated.

2 floydalgorithm It is the simplest algorithm of the shortest path. It can calculate the shortest path between any two points in the graph. The time complexity of floyd algorithm is o(n^3). if it is a graph without edge weight, the distance between two connected points is set to dis[i][j]=1. the two unrelated points are set to infinity. floyd algorithm can judge I j Are the two points connected?
3 floyd algorithm does not allow all weights to be negative. The shortest distance between any two points can be found. It deals with undirected graphs.
4. The disadvantage is that the time complexity is relatively high and it is not suitable for calculating large amounts of data.

If dis [i] [i]!= 0, then there is a ring.  

6 If floyd is used to find the minimum value, dis is initialized as INF, and - 1 is initialized as maximum value.

7. Template:

  1. #define INF 0xFFFFFFF   
  2. #define MAXN 1010   
  3. int dis[MAXN][MAXN];  
  4.   
  5. /*If it's a minimum, initialize it to INF.*/  
  6. void init(){  
  7.      for(int i = 1 ; i <= n ; i++){  
  8.         for(int j = 1 ; j <= n ; j++)  
  9.              dis[i][j] = INF;  
  10.         dis[i][i] = 0;  
  11.      }  
  12. }  
  13.   
  14. /*If the maximum value is obtained, it is initialized to -1.*/  
  15. void init(){  
  16.      for(int i = 1 ; i <= n ; i++){  
  17.         for(int j = 1 ; j <= n ; j++)  
  18.              dis[i][j] = -1;  
  19.      }  
  20. }  
  21.   
  22. /*floyd algorithm*/  
  23. void folyd(){  
  24.         for(int k = 1 ; k <= n ; k++){/*Enumerate n points to update dis*/  
  25.             for(int i = 1 ; i <= n ; i++){  
  26.                 for(int j = 1 ; j <= n ; j++)  
  27.                   if(dis[i][k] != -1 && dis[j][k] != -1)/*If you add this sentence to the maximum value*/  
  28.                      dis[i][j] = min(dis[i][k]+dis[k][j] , dis[i][j]);   
  29.             }   
  30.        }  
  31.  }  
  32.    
  1. #define INF 0xFFFFFFF  
  2. #define MAXN 1010  
  3. int dis[MAXN][MAXN];  
  4.   
  5. /*If it's a minimum, initialize it to INF.*/  
  6. void init(){  
  7.      for(int i = 1 ; i <= n ; i++){  
  8.         for(int j = 1 ; j <= n ; j++)  
  9.              dis[i][j] = INF;  
  10.         dis[i][i] = 0;  
  11.      }  
  12. }  
  13.   
  14. /*If the maximum value is obtained, it is initialized to -1.*/  
  15. void init(){  
  16.      for(int i = 1 ; i <= n ; i++){  
  17.         for(int j = 1 ; j <= n ; j++)  
  18.              dis[i][j] = -1;  
  19.      }  
  20. }  
  21.   
  22. /*floyd algorithm*/  
  23. void folyd(){  
  24.         for(int k = 1 ; k <= n ; k++){/*Enumerate n points to update dis*/  
  25.             for(int i = 1 ; i <= n ; i++){  
  26.                 for(int j = 1 ; j <= n ; j++)  
  27.                   if(dis[i][k] != -1 && dis[j][k] != -1)/*If you add this sentence to the maximum value*/  
  28.                      dis[i][j] = min(dis[i][k]+dis[k][j] , dis[i][j]);   
  29.             }   
  30.        }  
  31.  }  
  32.    

floyd extension:

How to use floyd to find the point where the shortest path travels: 1. Another matrix P is used here. Its definition is as follows: if the value of P (i j) is p, it means that the shortest path from I to j is I - > p... - > j, that is to say, P is the first point before J in the shortest path from I to J.

The initial value of 2 P matrix is p(ij) = j. With this matrix, it's easy to find the shortest path. For i to j, find P (ij), let p, know the path i - > P. -> j; then go to p(pj), if the value is q, the shortest path from P to j is p - > Q -> j; then go to p(qj), if the value is r, the shortest path from i to q is Q > R -> q; so repeated, the answer will be obtained.

3. But how to fill in the value of P matrix dynamically? Recall that when D (i j) > D (i k) +d (kj), the shortest path from I to j should be changed to I - > k - > k - > j, but the value of D (ik) is known, in other words, I - > k is known, so the first city of K (i - > k) on I - > K is also known, of course, because it is necessary to change to I - >. The first city in P (ij) is p (ik). So once d(ij)>d(ik)+d(kj) is found, p(ik) is deposited in p(ij).

Code 4:

  1. int dis[MAXN][MAXN];  
  2. int path[MAXN][MAXN];  
  3.   
  4. void floyd(){  
  5.       int  i, j, k;  
  6.       /*First initialize to j*/  
  7.       for (i = 1; i <= n; i++){  
  8.            for (j = 1; j <= n; j++)  
  9.                path[i][j] = j;  
  10.       }  
  11.       for (k = 1; k <= n; k++){/*Enumeration of n points*/  
  12.           for (i = 1; i <= n; i++){  
  13.               for (j = 1; j <= n; j++){  
  14.                    if (dis[i][j] > dis[i][k]+dis[k][j]){  
  15.                          path[i][j] = path[i][k];/*Update to path[i][k]*/  
  16.                          dis[i][j] = dis[i][k]+dis[k][j];  
  17.                     }  
  18.               }  
  19.            }  
  20.       }  
  21. }  
  1. int dis[MAXN][MAXN];  
  2. int path[MAXN][MAXN];  
  3.   
  4. void floyd(){  
  5.       int  i, j, k;  
  6.       /*First initialize to j*/  
  7.       for (i = 1; i <= n; i++){  
  8.            for (j = 1; j <= n; j++)  
  9.                path[i][j] = j;  
  10.       }  
  11.       for (k = 1; k <= n; k++){/*Enumeration of n points*/  
  12.           for (i = 1; i <= n; i++){  
  13.               for (j = 1; j <= n; j++){  
  14.                    if (dis[i][j] > dis[i][k]+dis[k][j]){  
  15.                          path[i][j] = path[i][k];/*Update to path[i][k]*/  
  16.                          dis[i][j] = dis[i][k]+dis[k][j];  
  17.                     }  
  18.               }  
  19.            }  
  20.       }  
  21. }  

2. floyd Solves the Minimum Ring in Rings

1 Why do we need to find the minimum loop before updating the shortest path?
In the k-level loop, we are looking for a ring whose maximum node is k, while the Dist array stores the shortest path through the k-1 node at the end of the k-1 loop, that is to say, the shortest path obtained above does not pass through the k-point, which just meets our requirements. Why? Assuming that the nodes i and j in the ring are directly connected with k, if the shortest path through K is found first, then there will be such a case: the shortest path from i to j passes through K. In this way, no ring can be formed.

2. The proof of the improved algorithm of minimum ring:
The maximum node in a ring is k (the largest number), and the two points connected with it are I and J. The shortest length of the ring is g [i] [k] + G [k] [j] + dis [i] [j] (in the path from I to j, all nodes are less than the shortest path length of k). According to the principle of floyd, dist[i][j] represents the shortest path from I to j after k-1 times of the outermost cycle. In summary, the algorithm can find the smallest ring in the graph.

3 Why do you want a value array?
Because dis arrays are changing all the time, it can't express the distance between the original two points.

4 There must be at least three different points in forming a ring, and two points cannot be considered as rings.
5 code:

  1. int mincircle = INF;  
  2. int dis[MAXN][MAXN];  
  3. int value[MAXN][MAXN];  
  4.   
  5. void floyd(){  
  6.      memcpy(value , dis , sizeof(value));  
  7.      for(int k = 1 ; k <= n ; k++){  
  8.           /*Find the smallest ring without the k-th point*/  
  9.           for(int i = 1 ; i < k ; i++){/*To k-1*/  
  10.                for(int j = i+1 ; j < k ; j++)/*To k-1*/  
  11.                    mincircle = min(mincircle , dis[i][j]+value[i][k]+value[k][j]);/*Undirected graph*/  
  12.                    mincircle = min(mincircle , dis[i][j] +value[i][k]+value[k][j]);/*Represents I - > k, K - > J with edges*/  
  13.            }  
  14.           /*Update the Shortest Path*/  
  15.           for(int i = 1 ; i <= n ; i++){  
  16.                for(int j = 1 ; j <= n ; j++)  
  17.                    dis[i][j] = min(dis[i][k]+dis[k][j] , dis[i][j]);  
  18.           }  
  19.      }    
  20. }  
  1. int mincircle = INF;  
  2. int dis[MAXN][MAXN];  
  3. int value[MAXN][MAXN];  
  4.   
  5. void floyd(){  
  6.      memcpy(value , dis , sizeof(value));  
  7.      for(int k = 1 ; k <= n ; k++){  
  8.           /*Find the smallest ring without the k-th point*/  
  9.           for(int i = 1 ; i < k ; i++){/*To k-1*/  
  10.                for(int j = i+1 ; j < k ; j++)/*To k-1*/  
  11.                    mincircle = min(mincircle , dis[i][j]+value[i][k]+value[k][j]);/*Undirected graph*/  
  12.                    mincircle = min(mincircle , dis[i][j] +value[i][k]+value[k][j]);/*Represents I - > k, K - > J with edges*/  
  13.            }  
  14.           /*Update the Shortest Path*/  
  15.           for(int i = 1 ; i <= n ; i++){  
  16.                for(int j = 1 ; j <= n ; j++)  
  17.                    dis[i][j] = min(dis[i][k]+dis[k][j] , dis[i][j]);  
  18.           }  
  19.      }    
  20. }  

Bellman_Ford (weights can be positive or negative) is used to judge negative rings.

1 Bellman_Frod can compute the shortest path problem with negative edge weights. It is suitable for directed and undirected graphs. It is used to solve the shortest path from source to any point.

2 In graphs with positive and negative edge weights, rings have three kinds: zero rings, positive rings and negative rings. If there are zero rings and positive rings, the path will not change after removal, and if there are negative rings, the shortest path will not exist. So since there is no negative ring, the shortest path only passes through n-1 points except the source point, so the shortest path from the source point to each point can be obtained through n-1 relaxation.

3. Time complexity o(n*m);
4 If there are rings, dis arrays can be updated after n-1 relaxation operations.
5 Template:

  1. /* 
  2. Applicable conditions: 
  3. 1 Single source shortest path 
  4. 2 Directed and undirected graphs 
  5. 3 Border weights can be positive or negative 
  6. */  
  7.   
  8. #define INF 0xFFFFFFF   
  9. #define MAXN 1010*2   
  10. int dis[MAXN];/*dis[i]Represents the shortest path from source point to point i*/  
  11. strucu Edge{  
  12.    int x;  
  13.    int y;  
  14.    int value;  
  15. }e[MAXN];  
  16.   
  17. /*Return the minimum*/  
  18. int min(int a , int b){  
  19.     return a < b ? a : b;  
  20. }  
  21.   
  22. /*Processing into undirected graph*/  
  23. void input(){  
  24.      for(int i = 0 ; i < m ; i++){  
  25.         scanf("%d%d%d" , e[i].x , &e[i].y , &e[i].value);  
  26.         e[i+m].x = e[i].y;/*Pay attention to places*/  
  27.         e[i+m].y = e[i].x;/*Pay attention to places*/  
  28.         e[i+m].value = e[i].value;            
  29.      }  
  30. }  
  31.   
  32. /*Suppose there are n points and m edges.*/  
  33. void Bellman_Ford(int s){  
  34.     /*Initialize dis array*/  
  35.     for(int i = 1 ; i <= s ; i++)  
  36.          dis[i] = INF;  
  37.     dis[s] = 0;  
  38.     for(int i = 1 ; i < n ; i++){/*Do n-1 relaxation*/  
  39.        for(int j = 0 ; j < 2*m ; j++){/*Enumerate 2*m edges each time because it is undirected graph*/  
  40.           if(dis[e[j].y] > dis[e[j].x] + e[j].value)  
  41.            dis[e[j.].y] = dis[e[i].x]+e[j].value;/*Update dis[e[j.y]*/  
  42.           }  
  43.        }  
  44.     }  
  45. }  
  1. /* 
  2. Applicable conditions: 
  3. 1 Single source shortest path 
  4. 2 Directed and undirected graphs 
  5. 3 Border weights can be positive or negative 
  6. */  
  7.   
  8. #define INF 0xFFFFFFF  
  9. #define MAXN 1010*2  
  10. int dis[MAXN];/*dis[i]Represents the shortest path from source point to point i*/  
  11. strucu Edge{  
  12.    int x;  
  13.    int y;  
  14.    int value;  
  15. }e[MAXN];  
  16.   
  17. /*Return the minimum*/  
  18. int min(int a , int b){  
  19.     return a < b ? a : b;  
  20. }  
  21.   
  22. /*Processing into undirected graph*/  
  23. void input(){  
  24.      for(int i = 0 ; i < m ; i++){  
  25.         scanf("%d%d%d" , e[i].x , &e[i].y , &e[i].value);  
  26.         e[i+m].x = e[i].y;/*Pay attention to places*/  
  27.         e[i+m].y = e[i].x;/*Pay attention to places*/  
  28.         e[i+m].value = e[i].value;            
  29.      }  
  30. }  
  31.   
  32. /*Suppose there are n points and m edges.*/  
  33. void Bellman_Ford(int s){  
  34.     /*Initialize dis array*/  
  35.     for(int i = 1 ; i <= s ; i++)  
  36.          dis[i] = INF;  
  37.     dis[s] = 0;  
  38.     for(int i = 1 ; i < n ; i++){/*Do n-1 relaxation*/  
  39.        for(int j = 0 ; j < 2*m ; j++){/*Enumerate 2*m edges each time because it is undirected graph*/  
  40.           if(dis[e[j].y] > dis[e[j].x] + e[j].value)  
  41.            dis[e[j.].y] = dis[e[i].x]+e[j].value;/*Update dis[e[j.y]*/  
  42.           }  
  43.        }  
  44.     }  
  45. }  

SPFA (weights can be positive or negative), judging negative rings.
1 is used to solve the shortest path of single source and the shortest path from source to any point.
2 algorithm introduction: establish a queue q, the initial queue has only one starting point, in the establishment of an array dis record starting point to all the shortest path, and initialize the array. Then the relaxation operation is carried out, using the points in the queue to refresh the starting point to all the shortest paths. If the refresh point is successful and the refresh point is no longer in the queue, the point is added to the end of the queue and repeated until the queue is empty.
3 Time Complexity: O (k e), K refers to the average number of teams entering all vertices. It can be proved that k<=2, e is the number of edges.

4. SPFA can be used to determine whether there is a ring or not. If so, the relaxation operation with one edge is greater than or equal to n.
5 Template:

  1. /* 
  2. 1 n Point m edge 
  3. 2 Adjacent table storage graph: first[i] stores the number of the first edge of node i, and nest[i] stores the number of the next edge of node I. 
  4. 3 star[i]Represents the starting point of the edge numbered i, the end[i] denotes the end point of the edge numbered i, and the value[i] denotes the weight of the edge numbered I. 
  5. 4 dis[i] Shortest path from source point to i 
  6. */  
  7.   
  8. #define MAXN 1010   
  9. #define INF 0xFFFFFFF   
  10.   
  11. int n , m;  
  12. int first[MAXN] , next[MAXN];  
  13. int star[MAXN] , end[MAXN] , value[MAXN];  
  14. int dis[MAXN];  
  15. queue<int>q;  
  16.   
  17. /*input*/  
  18. void input(){  
  19.      scanf("%d%d" , &n , &m);  
  20.      /*Initialize the header*/  
  21.      for(int i = 1 ; i <= n ; i++){  
  22.         first[i] = -1;  
  23.         next[i] = -1;  
  24.      }  
  25.      /*Read in m edges*/  
  26.      for(int i = 0 ; i < m ; i++){  
  27.         scanf("%d%d%d" , &star[i] , &end[i] , &value[i]);  
  28.         star[i+m] = end[i];  
  29.         end[i+m] = star[i];  
  30.         value[i+m] = value[i];  
  31.   
  32.         next[i] = first[star[i]];/*To insert the header, move the original header back*/  
  33.         first[star[i]] = i;/*Insert header*/  
  34.         next[i+m] = first[star[i+m]];  
  35.         first[star[i+m]] = i+m;  
  36.      }  
  37. }  
  38.   
  39. /*SPFA*/  
  40. void SPFA(int s){  
  41.      while(!q.empty())  
  42.           q.pop();  
  43.      int vis[MAXN];  
  44.      memset(vis , 0 , sizeof(vis));  
  45.      /*Initialize dis*/  
  46.      for(int i = 1 ; i <= n ; i++)  
  47.           dis[i] = INF;  
  48.      dis[s] = 0;  
  49.      q.push(s);/*Queuing Source Points*/  
  50.      vis[s] = 1;/*Source marker 1*/  
  51.      while(!q.empty()){  
  52.           int x = q.front();  
  53.           q.pop();  
  54.           vis[x] = 0;/*Note that this is marked as 0 again to indicate that you are out of the team.*/  
  55.           /*Enumeration of all edges related to point x*/  
  56.           for(int i = first[x] ; i != -1 ; i = next[i]){  
  57.              if(dis[end[i]] > dis[x] + value[i]){/*Relaxation operation, using trigonometric inequalities*/  
  58.                dis[end[i]] = dis[x] + value[i];  
  59.                if(!vis[end[i]]){/*If the point is no longer in the queue*/  
  60.                   vis[end[i]] = 1;                  
  61.                   q.push(end[i]);  
  62.                }  
  63.              }  
  64.           }  
  65.      }  
  1. /* 
  2. 1 n Point m edge 
  3. 2 Adjacent table storage graph: first[i] stores the number of the first edge of node i, and nest[i] stores the number of the next edge of node I. 
  4. 3 star[i]Represents the starting point of the edge numbered i, the end[i] denotes the end point of the edge numbered i, and the value[i] denotes the weight of the edge numbered I. 
  5. 4 dis[i] Shortest path from source point to i 
  6. */  
  7.   
  8. #define MAXN 1010  
  9. #define INF 0xFFFFFFF  
  10.   
  11. int n , m;  
  12. int first[MAXN] , next[MAXN];  
  13. int star[MAXN] , end[MAXN] , value[MAXN];  
  14. int dis[MAXN];  
  15. queue<int>q;  
  16.   
  17. /*input*/  
  18. void input(){  
  19.      scanf("%d%d" , &n , &m);  
  20.      /*Initialize the header*/  
  21.      for(int i = 1 ; i <= n ; i++){  
  22.         first[i] = -1;  
  23.         next[i] = -1;  
  24.      }  
  25.      /*Read in m edges*/  
  26.      for(int i = 0 ; i < m ; i++){  
  27.         scanf("%d%d%d" , &star[i] , &end[i] , &value[i]);  
  28.         star[i+m] = end[i];  
  29.         end[i+m] = star[i];  
  30.         value[i+m] = value[i];  
  31.   
  32.         next[i] = first[star[i]];/*To insert the header, move the original header back*/  
  33.         first[star[i]] = i;/*Insert header*/  
  34.         next[i+m] = first[star[i+m]];  
  35.         first[star[i+m]] = i+m;  
  36.      }  
  37. }  
  38.   
  39. /*SPFA*/  
  40. void SPFA(int s){  
  41.      while(!q.empty())  
  42.           q.pop();  
  43.      int vis[MAXN];  
  44.      memset(vis , 0 , sizeof(vis));  
  45.      /*Initialize dis*/  
  46.      for(int i = 1 ; i <= n ; i++)  
  47.           dis[i] = INF;  
  48.      dis[s] = 0;  
  49.      q.push(s);/*Queuing Source Points*/  
  50.      vis[s] = 1;/*Source marker 1*/  
  51.      while(!q.empty()){  
  52.           int x = q.front();  
  53.           q.pop();  
  54.           vis[x] = 0;/*Note that this is marked as 0 again to indicate that you are out of the team.*/  
  55.           /*Enumeration of all edges related to point x*/  
  56.           for(int i = first[x] ; i != -1 ; i = next[i]){  
  57.              if(dis[end[i]] > dis[x] + value[i]){/*Relaxation operation, using trigonometric inequalities*/  
  58.                dis[end[i]] = dis[x] + value[i];  
  59.                if(!vis[end[i]]){/*If the point is no longer in the queue*/  
  60.                   vis[end[i]] = 1;                  
  61.                   q.push(end[i]);  
  62.                }  
  63.              }  
  64.           }  
  65.      }  

Topics: less