Single-the shortest circuit problem with negative edges-Bellman-Ford algorithm and its optimized SPFA algorithm have the shortest road algorithm with negative power

2023-03-18  

1. Bellman-Ford algorithm is used to process the shortest circuit of negative edges in the diagram. When there is negative edge in the figure, Dijkstra () cannot be used. The shortest circuit calculated will have problems. It should be noted that if there is a negative car circuit in the picture, the shortest circuit is likely not to exist (when the negative circuit does not affect the path we want to go, it does not affect the result), the idea of the Bellman-Ford algorithm is very simple, and its The application scenarios are also relatively limited.

First of all, when performing relaxation operations, you need to pay attention to update other nodes with the last updated distance, that is, you need to keep the last distance. A series, and an important use scenario of the BF algorithm is to deal with the shortest circuit problem that limits the number of edges, which may cause errors.

Here you have the shortest and shortest problem with the number of edges that pass through. You can give a specific instance. For example, we often cannot reach directly when traveling, and need to be replaced. By multiplication is one side, the price is the weight. You need a transfer route with the smallest total price, but there is another factor that will have an impact, that is, each transfer will affect your mood, so you hope that the number of transfers is limited The corresponding is that there are restrictions on the shortest border.

code instance: a n point, the side of the m, the direction of the edge, the border power may be negative, and the maximum distance from the K -strip edge from point No. 1 to the nager is found.

Here use the structure to save edge

#include <iOSTREAM> 
 #include <algorithm> 
 #include <cstring> 

 using namespace std; 

 const int n = 510, m = 10010; 

 Struct Edge // Use the structure of the structure 
 {{ 
     int a, b, c; 
 } Edges [m]; 

 int n, m, k; 
 int dist [n]; 
 int last [n]; 

 void Bellman_ford () 
 {{ 
     Memset (distal, 0x3F, sizeof dist); 
     dist [1] = 0; // Select a starting point 
    
     For (int i = 0; i <k; i ++) // k is the number of edges 
     {{ 
         Memcpy (last, distal, sizeof dist); 
        
         For (int j = 0; j <m; j ++) // will update all edges at a time every cycle 
         {{ 
             auto e = edges [j]; 
             be [e.b] = min (dist], last [e.a] + e.c); // 
         } 
     } 
 } 

 int Main () 
 {{ 
     scanf ("%d%d%d", & n, & m, & k); 
     for (int i = 0; i <m; i ++) 
     {{ 
         int a, b, c; 
         scanf ("%d%d%d", & a, & b, & c); 
         EDGES [i] = {a, b, c}; 
     } 
    
     Bellman_ford (); 
    
     if (orx [n]> 0x3F3F3F3F / 2) PUTS ("IMPOSSIBLE"); 
     else core << dist [n] << Endl; 
    
     Return 0; 
 }

2, SPFA algorithm

This algorithm is an optimization of the BF algorithm. It is available when there is no negative ring in the figure. From the observation of the code above, we can see that every cycle will be updated, but this is not needed. In fact, it is not needed. Because only the distance of the current point is updated, that is to say, the distance becomes smaller, so you need to update the point connected to this border. This algorithm is a bit like the Dijkstra algorithm. Do it. Its time complexity is O (m), and the worst case is O (NM).

#include <cstring> 
 #include <iOSTREAM> 
 #include <algorithm> 
 #include <queue> 

 using namespace std; 

 const int n = 100010; 

 int n, m; 
 int h [n], w [n], e [n], ne [n], idx; 
 int dist [n]; 
 BOOL ST [n]; // Store whether each point is in the queue 

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

 // Time complexity o (m) 
 int spfa () 
 {{ 
     Memset (distal, 0x3F, sizeof dist); 
     dist [1] = 0; 
    
     queue <int> q; 
     q.push (1); 
     st [1] = true; 
    
     While (q.size ()) // The queue has all the points to be updated 
     {{ 
         int T = q.front (); 
         q.pop (); 
        
         st [t] = false; 
        
         for (int i = h [t]; i! = -1; i = NE [i]) // Like all the points of connecting all edge of this point 
         {{ 
             int j = e [i]; 
             if (orSt [J]> Dist [t] + w [i]) 
             {{ 
                 be [j] = dist] + w [i]; 
                 if (! ST [J]) // If J is already in the queue, you do not need to insert J to avoid repeating the team 
                 {{ 
                     q.push (j); 
                     st [j] = true; 
                 } 
             } 
         } 
     } 
    
     Return dist [n]; 
 } 

 int Main () 
 {{ 
     scanf ("%d%d", & n, & m); 
    
     Memset (h, -1, sizeof h); 
    
     While (m-) 
     {{ 
         int a, b, c; 
         scanf ("%d%d%d", & a, & b, & c); 
         add (a, b, c); 
     } 
    
     int T = spfa (); 
    
     if (T == 0x3F3F3F3F) puts ("Impossible"); 
     else propf ("%d \ n", t); 
    
     Return 0; 
 }

SPFA an important application, whether there is a negative ring in the judgment diagram

#include <cstring> 
 #include <iOSTREAM> 
 #include <algorithm> 
 #include <queue> 

 using namespace std; 

 const int n = 2010, m = 100010; 

 int n, m; 
 int h [n], w [m], e [m], ne [m], IDX; 
 int dist [n], cNT [n]; 
 BOOL ST [n]; 

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

 BOOL SPFA () 
 {{ 
     queue <int> q; 
     For (int i = 1; i <= n; i ++) // All nodes join the team and mark 
     {{ 
         st [i] = true; 
         q.push (i); 
     } 
    
     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 (orSt [J]> Dist [t] + w [i]) 
             {{ 
                 be [j] = dist] + w [i]; 
                 cnt [j] = cNT [t] + 1; 
                
                 if (cnt [j]> = n) return true; // Depending on the drawer principle, there must be a negative ring 
                 if (! ST [J]) 
                 {{ 
                     q.push (j); 
                     st [j] = true; 
                 } 
             } 
         } 
     } 
    
     Return false; 
 } 

 int Main () 
 {{ 
     scanf ("%d%d", & n, & m); 
    
     Memset (h, -1, sizeof h); 
    
     While (m-) 
     {{ 
         int a, b, c; 
         scanf ("%d%d%d", & a, & b, & c); 
         add (a, b, c); 
     } 
    
     if (spfa ()) puts ("yes"); 
     else public ("no"); 
    
     Return 0; 
 }

source

Random Posts

python generate 417 yards (PDF417)

001-linux-IOCTL control of character device control — serial port send stonexinh

SpringBoot —— The principle of automatic assembly (dry goods)

setContentView (), Inflate () method Dream

Related analysis — Apriori algorithm and FPGROWTH algorithm mining rules calculate the confidence between frequent items