Several algorithms for the shortest path problem

Floyd algorithm

Conditions of Use

The shortest path of multiple sources can be found, and the negative weight side can be handled, but a negative loop cannot occur.

time complexity

O (n 3

explain

Floyed algorithm uses the method of dynamic programming.

       We first observe the above picture.

       Let ’s think about it. According to our previous experience, if we want to shorten the distance between any two points (for example, from vertex a to vertex b), we can only introduce a third point (vertex k) and pass this It is possible to shorten the original distance from vertex a to vertex b by transferring vertex k to a-> k-> b. So which of 1 ~ n is the vertex k of this transit? Sometimes, not only one point, but two or more points, the transfer will be shorter, namely a-> k1-> k2b-> or a-> k1-> k2 ...-> k-> i ...- > b. For example, the distance e [4] [3] from city 4 to city 3 (4-> 3) in the above picture was originally 12. If only transiting through city 1 (4-> 1-> 3), the distance will be shortened to 11 (e [4] [1] + e [1] [3] = 5 + 6 = 11). In fact, City 1 to City 3 can also be transited through City 2 to shorten the distance from City 1 to City 3 (e [1] [2] + e [2] [3] = 2 + 3 = 5 ). So if transiting through two cities at the same time, the distance from city 4 to city 3 will be further shortened to 10. Through this example, we found that each vertex may make the distance between the other two vertices shorter. Okay, let ’s generalize this question.

       When the third point is not allowed to pass between any two points, the shortest distance between these cities is the initial distance, as follows.

 

 If we set a transfer point between every two points, see if it is shorter before using this transfer point or after using it. The distance between the two points and the transfer point is already the shortest distance, so the final calculation It must be the shortest way out.

You only need to use the simplest and rude way to enumerate the starting point, ending point, and transit point.

State transfer equation:

d [i] [j] = min (d [i] [k] + d [k] [j], d [i] [j])

In this way, it is easy to write the core code of Floyd's algorithm.

It should also be noted that the Floyd algorithm cannot solve graphs with "negative weight loops" (or "negative weight loops") because graphs with "negative weight loops" have no shortest path. For example, the following graph does not have the shortest path from vertex 1 to vertex 3. Because 1-> 2-> 3-> 1-> 2-> 3->…-> 1-> 2-> 3, the shortest path is the shortest time every time a loop such as 1->-2> 3 is wound Will decrease by 1, and never find the shortest path. In fact, if there is a "negative weight loop" in a graph, there is no shortest path in this graph.

Core code

for (k = 1 ; k <= n; k ++) // enumeration transit point 
    for (i = 1 ; i <= n; i ++) // enumeration starting point         
        for (j = 1 ; j <= n; j ++)           // End point of enumeration 
            d [i] [j] = min (d [i] [k] + d [k] [j], d [i] [j]);

Dijkstra algorithm

Conditions of Use

Seeking the shortest path of a single source cannot handle negative weights.

time complexity

O (n 2

explain

The Dijkstra algorithm uses the greedy method, d [i] represents the shortest distance from the starting point s0 to i.

Starting from the starting point s0, select the unvisited point i closest to s0, which is the smallest d [i], because the edge weight is positive, there will be no shorter path to reach i, ensuring the correctness of greed . Then use i as an intermediate point, update the shortest distance of the point that can be reached through i, and continue to greedy to find the nearest point that has not been visited. After n times of greed, the algorithm ends.

Look at the picture:

 

According to this figure, the Dijkstra algorithm should be well understood.

Core code

for (i = 1 ; k <= n; k ++ ) 
{ 
    maxn = 0x7fffffff ;
     for (j = 1 ; j <= n; j ++)                  // Find the smallest d [j] 
    {
         if (! vis [j ] && d [j] < maxn) 
        { 
            maxn = d [j]; 
            k = i; 
        } 

    } 
    vis [k] = 1 ;
     for (j = 1 ; j <= n; j ++)           // k as an intermediate point, D [j] 
        if  (w [k] [j]) to
        {
            d [j] = min {d [k] + w [k] [j], d [j]}; 
        } 
}

SPFA algorithm

Conditions of Use

Find the shortest path of a single source, can handle negative weight edges

time complexity

For sparse graphs, O (km), k is a smaller constant, and for dense graphs or constructed grid graphs, it will be increased to O (n * m)

explain

Create a queue. At the beginning, there is only the starting point in the queue. Create a table to record the shortest path from the starting point to all points (the initial value of the table must be assigned a maximum value, and the path from this point to itself is assigned 0). Then perform the slack operation, use the points in the queue to refresh the shortest path from the starting point to all points, and if the refresh is successful and the refreshed point is not in the queue, add the point to the end of the queue. Repeat execution until the queue is empty.

Figure:

 

 

Source A enters the team first, and AB relaxes

Insert picture description here

Extend the side connected to A, B, C join the team and relax.

Insert picture description here

B and C start to expand respectively, D enters the team and relaxes

Insert picture description here

D leaves the team, E enters the team and relaxes.

Insert picture description here

E leaves the queue, the queue is empty, the shortest path from the source to all points has been found, and the shortest path of A-> E is 8

Insert picture description here

The above is the process of SPFA algorithm.

Core code

q.push (s); 
vis [s] = 1 ;   // The source point s is enqueued and marked enqueue 
while (q.size ()) 
{ 
       u = q.front (); q.pop (); vis [ u] = 0 ;         // Remove the head of the team and mark it as not joining the team 
       for (i = head [u]; i; i = next [i]) 
       { 
              v = ver [i]; 
              w = edge [i];
               if ( dis [u] + w < dis [v]) 
              { 
                     dis [v] = dis [u] + w;
                      if (! vis [v]) {q.push (v); vis [v] = 1 ;}     / /If not in the queue, enqueue, mark enqueue 
              }     
       } 
}

 

Guess you like

Origin www.cnblogs.com/arknight/p/12723319.html