Graph theory - the shortest path: Floyd, Dijkstra, Bellman-Ford, SPFA algorithm and smallest ring problem

Reprinted from - " https://www.cnblogs.com/ninedream/p/11186049.html

A .Floyd algorithm

  Used to calculate the shortest path between any two nodes.

        Reference five20 's blog

        The basic idea of ​​Floyd algorithm works as follows: no more than two possible from any arbitrary node A to node B is the shortest path, directly from 1 A to B, 2 from A to B via a plurality of nodes, so we assume that dist ( AB) is from node a to node B is the shortest path for each node K, we check dist (AK) + dist (KB) <dist (AB) is established or if established from a to B and then to prove K a shorter path than the direct path to B, we set dist (AB) = dist (AK) + dist (KB), this way, when we complete traverse all the nodes K, dist (AB) is recorded the shortest path from a to B of.

 Five standard code is as follows:

Copy the code
for(k=1;k<=n;k++)
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++) {
            if(dis[i][k]+dis[k][j]<dis[i][j]) {
                 dis[i][j]=dis[i][k]+dis[k][j];
    }
} 
Copy the code

   But here we must note the nesting order cycle, if all the check nodes K on the innermost layer, then the result will be incorrect, and why? Because this will prematurely i to j to determine the shortest path down, and when there is a shorter path behind no longer be updated.

  

  More about Floyd algorithm, for details see: Floyd algorithm for Baidu Encyclopedia link

 

Two .Dijkstra algorithm:

  Applicable to a weight of a non-single-source shortest path negative FIG.

  Fibonacci heap optimization of time complexity is O (E + VlogV), but in fact only theoretical value, the actual basically reach.

  Algorithms ideas:

  Reference to the Yantian Wen 's blog

  • Specify a node, for example, we have to calculate the shortest path 'A' to another node
  • Introduction of two sets (S, U), S the set of points (and the corresponding shortest length) contains the shortest path has been determined, the U-set comprising a point not determined shortest path (the path A and to the point of attention as as shown in FIG, A->Csince initially when not directly connected ∞ )
  • A set of two initialization, the initial set time S for the current node only calculated A->A = 0,
    when U is initially set  A->B = 4, A->C = ∞, A->D = 2, A->E = ∞, knock blackboard! ! ! The next two steps are to be the core!
  • To find the shortest path from a point U in the collection, the collection S is added, e.g. A->D = 2
  • U update the collection route, if ( 'D 到 B,C,E 的距离' + 'AD 距离' < 'A 到 B,C,E 的距离' ) the updated U
  • 4,5 perform a two-step cycle, until the end of the traverse to obtain the shortest path to the other nodes A

  Simple Version time complexity O (n²) algorithm code as follows:

Copy the code
void Dijkstra()
{
    memset(dis, 0x1f, sizeof(dis));
    dis[1] = 0;
    for (int i=1; i<=n; i++) {
        int min_len = 1e9, k = 0;
        for (int j=1; j<=n; j++)     
            if (!vis[j] && dis[j] < min_len) {
                min_len = dis[j];
                k = j;
            }
        vis[k] = 1;     
        for (int j=h[k]; j!=-1; j=edge[j].next) {    
            int to = edge[j].to, w = edge[j].w;
            if (!vis[to] && dis[to] > dis[k]+w) {
                dis[to] = dis[k]+w;
            }
        }
    }
}
Copy the code

 

  Stability time complexity O (mlogn) stack optimization (instead of the priority queue) code is as follows:

Copy the code
void Dijkstra_Heap()
{
    priority_queue<pair<int, int> > q;
    memset(dis, 0x3f, sizeof(dis));
    memset(vis,0,sizeof(v));
    dis[1] = 0; 
    q.push(make_pair(0, 1));
    while (!q.empty()) {
        int now = q.top().second;
        q.pop();
        if (vis[now]) continue;
        vis[now] = 1;
        for (int i=h[now]; i!=-1; i=edge[i].next) {
            int to = edge[i].to, w = edge[i].w;
            if (!vis[to] && dis[to]>dis[now]+w) {
                dis[to] = dis[now] + w;
                q.push(make_pair(-dis[to], to));
            }
        }
    }
} 
Copy the code

Here's a small show operating on the priority queue:

  Since the STL large root default priority queue stack, so when using the front push function simply needs to add a sorted data '-' can be.

 

  On the choice of the Dijkstra algorithm, for sparse graphs , since n and m are relatively close, so choose the heap optimization algorithm ; for dense graph , since the multi-point less side, so choose simple version of the algorithm .

 

  More about Dijkstra's algorithm, for details see: Dijkstra's algorithm Baidu Encyclopedia link

   Recommended blog: data structures, algorithms --Dijkstra clearest explanation

 

Three .Bellman-Ford algorithm

  Reference blog: graphic Bellman Ford - Algorithm

It can be used to address the following issues:

  • A presence or absence from the path to each node (with calculated values ​​reach course);
  • A shortest path starting from each node (minimum time, or at least paths, etc.)
  • If there is a negative loop (the sum of weights is negative) FIG.
  • There shortest limit of the number of sides

  Algorithms ideas:

  1.  When initializing the start point to each vertex v s distance dist (s-> v) assigned ∞, dist (s-> s) assigned 0
  2.  Up to n-1 for subsequent traversal operation, all the sides relaxation operation, it is assumed:
  3.  The so-called relaxation, with the side ab example, if dist (a) reaches the total number of the representative starting point s it takes a point, dist (b) the total number of the representative starting point s it takes to reach the point b, weight (ab) representative of edge ab weight, if there is:
  4.  (dist(a) +weight(ab)) < dist(b)
  5.  B indicates the presence of the shorter path, s -> ...-> a-> b, updating the total cost of the point b (dist (a) + weight (ab)), a parent node
  6.  After traversing all over, if more traversed once, but also to obtain some nodes s shorter path, then there is a negative loop described

  Thoughts on the Dijkstra algorithm (Dijkstra algorithm) the biggest difference is carried out every time a new start "slack" from the source point s update operation, and Dijkstra is expanded outward from the source point adjacent processed one by one node, not to repeat the processing node, it can also be seen here Dijkstra relatively higher point efficiency.

   Here there is a limited number of edges k Bellman_ford algorithm template:

Copy the code
void Bellman_ford()
{
    memset(dis,0x1f,sizeof(dis));
    dis[1]=0;
    for(int i=1;i<=k;i++)
    {
        memcpy(last,dis,sizeof(last));
        for(int j=1;j<=m;j++)
        {
            int u=edge[j].u,v=edge[j].v,w=edge[j].w;
            if(dis[v]>last[u]+w)dis[v]=last[u]+w;
        }
    }
}
Copy the code

  

  More on Bellman-Ford algorithm, for details see: Bellman-Ford algorithm Baidu Encyclopedia link

 

Four .SPFA algorithm

  SPFA is "fast algorithm SPFA on the shortest path" segment where Ding Xi'an Jiaotong University, was published in 1994 and "Xi'an Jiaotong University", he said SPFA faster than Dijkstra fast and run SPFA speed V times than Floyd speed in it fast.
  And it turns out SPFA algorithm is limited, he does not apply to dense graph, dense graph for special circumstances, SPFA complexity and BellmanFord the same time.

  Application: Suitable for weight values ​​are negative, and no single source shortest path map negative ring, Dissertation complexity O (kE), k is the number of each node into the Queue, and generally k <= 2, but complexity is here to prove problematic, in fact, should be SPFA worst-case O (VE).

  Note: SPFA trellis algorithm is very slow

  Algorithms ideas:

  Reference to the small day bit of blog

  •  SPFA (Shortest Path Faster Algorithm) [FIG storage for the adjacent table].
  •  A queue Bellman-Ford algorithm implemented, reducing unnecessary redundant computations.
  •  The general process algorithm is a queue for maintenance. The initial source of added queue. Every time an element is removed from the queue, and all the relaxation with his neighbor's point, if a point adjacent to the success of relaxation, it is into the team. The algorithm ends until the queue is empty. It can be determined source shortest path to all other points in time complexity O (kE) and a negative side can be processed.
  • SPFA very similar in form and BFS, BFS is different in a point out of the queue it is impossible to re-enter the queue, but SPFA, one point may be placed in the queue again after a queue, which is a point improvement over other after a point, over a period of time may itself be improved, then once again it is used to improve other points, such iterative down.
  •  Determine whether the negative ring: If the number of the queue exceeds a certain Enter negative times V ring (unable to process the SPFA negatively FIG ring) is present.

  code show as below:

Copy the code
void the SPFA () { 
    Memset (DIS, 0x3F, the sizeof (DIS)); 
    Memset (VIS, 0, the sizeof (VIS)); 
    Queue <int> Q; 
    DIS [. 1] = 0; VIS [. 1] =. 1; 
    Q .push (. 1); 
    the while {(q.empty ()!) 
        int q.front = now (); 
        q.pop (); VIS [now] = 0; 
        for (int I = H [now]; I! -1 =; Edge I = [I] .next) { 
            int = Edge to [I] .to, Edge = W [I] .W; 
            IF (DIS [now] + W <DIS [to]) {// point in the queue relaxation operation may be performed, without adding so here! ifq [to] conditions, and need to add below. 
                DIS [to] DIS = [now] + W; 
                IF q.push (to), VIS [to] =. 1 (VIS [to]!); 
            } 
        } 
    } 
}
Copy the code

 

  More about SPFA algorithm, for details see: SPFA algorithm Baidu Encyclopedia link

 

V. smallest ring problem

  Solutions:

  It refers to find a minimum cycle in a drawing ring, so that the right side of the ring pieces of the minimum value. Floyed the same time, the way may be calculated from the smallest ring.

  The shortest path between two points is denoted dis [i] [j], g [i] [j] as an edge <i, j> weights. 

  A maximum junction ring is k (the maximum number), it is connected with two points of i, j, the shortest length of the loop g [i] [k] + g [k] [j] + (i j is the path, all node numbers are less than the path length of k).

  The following Floyed principle, the outermost loop made k-1 times, DIS [i] [j] represents the i to j path, all node numbers are smaller than the shortest path k.

  In summary, the algorithm must be able to find the smallest ring in Fig.

  code show as below:

  Reference Coder_YX 's blog

Copy the code
 void floyd(){
     int MinCost = inf;
     for(int k=1;k<=n;k++){
         for(int i=1;i<k;i++)
             for(int j=i+1;j<k;j++)
                 MinCost = min(MinCost,dis[i][j]+mp[i][k]+mp[k][j]);//更新k点之前枚举ij求经过ijk的最小环
         for(int i=1;i<=n;i++)
             for(int j=1;j<=n;j++)
                 dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);      //更新k点
     }
     if(MinCost==inf)puts("It's impossible.");
     else printf("%d\n",MinCost);
 }
Copy the code

 

About four most shortest path algorithm conclusions:

 Reference xiazdong 's blog

(1) When the value is non-negative in power, by Dijkstra.
(2) in power has a negative value, and no negative circle, with the SPFA, SPFA negative ring can be detected, but can not output negative circle.
(3) in power has a negative value, and there may be a negative ring, with the BellmanFord, it can be detected and outputs a negative circle.
(4) SPFA NEGATIVE ring: when there is a point not less than V enqueue time, the negative ring.

A .Floyd algorithm

  Used to calculate the shortest path between any two nodes.

        Reference five20 's blog

        The basic idea of ​​Floyd algorithm works as follows: no more than two possible from any arbitrary node A to node B is the shortest path, directly from 1 A to B, 2 from A to B via a plurality of nodes, so we assume that dist ( AB) is from node a to node B is the shortest path for each node K, we check dist (AK) + dist (KB) <dist (AB) is established or if established from a to B and then to prove K a shorter path than the direct path to B, we set dist (AB) = dist (AK) + dist (KB), this way, when we complete traverse all the nodes K, dist (AB) is recorded the shortest path from a to B of.

 Five standard code is as follows:

Copy the code
for(k=1;k<=n;k++)
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++) {
            if(dis[i][k]+dis[k][j]<dis[i][j]) {
                 dis[i][j]=dis[i][k]+dis[k][j];
    }
} 
Copy the code

   But here we must note the nesting order cycle, if all the check nodes K on the innermost layer, then the result will be incorrect, and why? Because this will prematurely i to j to determine the shortest path down, and when there is a shorter path behind no longer be updated.

  

  More about Floyd algorithm, for details see: Floyd algorithm for Baidu Encyclopedia link

 

Two .Dijkstra algorithm:

  Applicable to a weight of a non-single-source shortest path negative FIG.

  Fibonacci heap optimization of time complexity is O (E + VlogV), but in fact only theoretical value, the actual basically reach.

  Algorithms ideas:

  Reference to the Yantian Wen 's blog

  • Specify a node, for example, we have to calculate the shortest path 'A' to another node
  • Introduction of two sets (S, U), S the set of points (and the corresponding shortest length) contains the shortest path has been determined, the U-set comprising a point not determined shortest path (the path A and to the point of attention as as shown in FIG, A->Csince initially when not directly connected ∞ )
  • A set of two initialization, the initial set time S for the current node only calculated A->A = 0,
    when U is initially set  A->B = 4, A->C = ∞, A->D = 2, A->E = ∞, knock blackboard! ! ! The next two steps are to be the core!
  • To find the shortest path from a point U in the collection, the collection S is added, e.g. A->D = 2
  • U update the collection route, if ( 'D 到 B,C,E 的距离' + 'AD 距离' < 'A 到 B,C,E 的距离' ) the updated U
  • 4,5 perform a two-step cycle, until the end of the traverse to obtain the shortest path to the other nodes A

  Simple Version time complexity O (n²) algorithm code as follows:

Copy the code
void Dijkstra()
{
    memset(dis, 0x1f, sizeof(dis));
    dis[1] = 0;
    for (int i=1; i<=n; i++) {
        int min_len = 1e9, k = 0;
        for (int j=1; j<=n; j++)     
            if (!vis[j] && dis[j] < min_len) {
                min_len = dis[j];
                k = j;
            }
        vis[k] = 1;     
        for (int j=h[k]; j!=-1; j=edge[j].next) {    
            int to = edge[j].to, w = edge[j].w;
            if (!vis[to] && dis[to] > dis[k]+w) {
                dis[to] = dis[k]+w;
            }
        }
    }
}
Copy the code

 

  Stability time complexity O (mlogn) stack optimization (instead of the priority queue) code is as follows:

Copy the code
void Dijkstra_Heap()
{
    priority_queue<pair<int, int> > q;
    memset(dis, 0x3f, sizeof(dis));
    memset(vis,0,sizeof(v));
    dis[1] = 0; 
    q.push(make_pair(0, 1));
    while (!q.empty()) {
        int now = q.top().second;
        q.pop();
        if (vis[now]) continue;
        vis[now] = 1;
        for (int i=h[now]; i!=-1; i=edge[i].next) {
            int to = edge[i].to, w = edge[i].w;
            if (!vis[to] && dis[to]>dis[now]+w) {
                dis[to] = dis[now] + w;
                q.push(make_pair(-dis[to], to));
            }
        }
    }
} 
Copy the code

Here's a small show operating on the priority queue:

  Since the STL large root default priority queue stack, so when using the front push function simply needs to add a sorted data '-' can be.

 

  On the choice of the Dijkstra algorithm, for sparse graphs , since n and m are relatively close, so choose the heap optimization algorithm ; for dense graph , since the multi-point less side, so choose simple version of the algorithm .

 

  More about Dijkstra's algorithm, for details see: Dijkstra's algorithm Baidu Encyclopedia link

   Recommended blog: data structures, algorithms --Dijkstra clearest explanation

 

Three .Bellman-Ford algorithm

  Reference blog: graphic Bellman Ford - Algorithm

It can be used to address the following issues:

  • A presence or absence from the path to each node (with calculated values ​​reach course);
  • A shortest path starting from each node (minimum time, or at least paths, etc.)
  • If there is a negative loop (the sum of weights is negative) FIG.
  • There shortest limit of the number of sides

  Algorithms ideas:

  1.  When initializing the start point to each vertex v s distance dist (s-> v) assigned ∞, dist (s-> s) assigned 0
  2.  Up to n-1 for subsequent traversal operation, all the sides relaxation operation, it is assumed:
  3.  The so-called relaxation, with the side ab example, if dist (a) reaches the total number of the representative starting point s it takes a point, dist (b) the total number of the representative starting point s it takes to reach the point b, weight (ab) representative of edge ab weight, if there is:
  4.  (dist(a) +weight(ab)) < dist(b)
  5.  B indicates the presence of the shorter path, s -> ...-> a-> b, updating the total cost of the point b (dist (a) + weight (ab)), a parent node
  6.  After traversing all over, if more traversed once, but also to obtain some nodes s shorter path, then there is a negative loop described

  Thoughts on the Dijkstra algorithm (Dijkstra algorithm) the biggest difference is carried out every time a new start "slack" from the source point s update operation, and Dijkstra is expanded outward from the source point adjacent processed one by one node, not to repeat the processing node, it can also be seen here Dijkstra relatively higher point efficiency.

   Here there is a limited number of edges k Bellman_ford algorithm template:

Copy the code
void Bellman_ford()
{
    memset(dis,0x1f,sizeof(dis));
    dis[1]=0;
    for(int i=1;i<=k;i++)
    {
        memcpy(last,dis,sizeof(last));
        for(int j=1;j<=m;j++)
        {
            int u=edge[j].u,v=edge[j].v,w=edge[j].w;
            if(dis[v]>last[u]+w)dis[v]=last[u]+w;
        }
    }
}
Copy the code

  

  More on Bellman-Ford algorithm, for details see: Bellman-Ford algorithm Baidu Encyclopedia link

 

Four .SPFA algorithm

  SPFA is "fast algorithm SPFA on the shortest path" segment where Ding Xi'an Jiaotong University, was published in 1994 and "Xi'an Jiaotong University", he said SPFA faster than Dijkstra fast and run SPFA speed V times than Floyd speed in it fast.
  And it turns out SPFA algorithm is limited, he does not apply to dense graph, dense graph for special circumstances, SPFA complexity and BellmanFord the same time.

  Application: Suitable for weight values ​​are negative, and no single source shortest path map negative ring, Dissertation complexity O (kE), k is the number of each node into the Queue, and generally k <= 2, but complexity is here to prove problematic, in fact, should be SPFA worst-case O (VE).

  Note: SPFA trellis algorithm is very slow

  Algorithms ideas:

  Reference to the small day bit of blog

  •  SPFA (Shortest Path Faster Algorithm) [FIG storage for the adjacent table].
  •  A queue Bellman-Ford algorithm implemented, reducing unnecessary redundant computations.
  •  The general process algorithm is a queue for maintenance. The initial source of added queue. Every time an element is removed from the queue, and all the relaxation with his neighbor's point, if a point adjacent to the success of relaxation, it is into the team. The algorithm ends until the queue is empty. It can be determined source shortest path to all other points in time complexity O (kE) and a negative side can be processed.
  • SPFA very similar in form and BFS, BFS is different in a point out of the queue it is impossible to re-enter the queue, but SPFA, one point may be placed in the queue again after a queue, which is a point improvement over other after a point, over a period of time may itself be improved, then once again it is used to improve other points, such iterative down.
  •  Determine whether the negative ring: If the number of the queue exceeds a certain Enter negative times V ring (unable to process the SPFA negatively FIG ring) is present.

  code show as below:

Copy the code
void the SPFA () { 
    Memset (DIS, 0x3F, the sizeof (DIS)); 
    Memset (VIS, 0, the sizeof (VIS)); 
    Queue <int> Q; 
    DIS [. 1] = 0; VIS [. 1] =. 1; 
    Q .push (. 1); 
    the while {(q.empty ()!) 
        int q.front = now (); 
        q.pop (); VIS [now] = 0; 
        for (int I = H [now]; I! -1 =; Edge I = [I] .next) { 
            int = Edge to [I] .to, Edge = W [I] .W; 
            IF (DIS [now] + W <DIS [to]) {// point in the queue relaxation operation may be performed, without adding so here! ifq [to] conditions, and need to add below. 
                DIS [to] DIS = [now] + W; 
                IF q.push (to), VIS [to] =. 1 (VIS [to]!); 
            } 
        } 
    } 
}
Copy the code

 

  More about SPFA algorithm, for details see: SPFA algorithm Baidu Encyclopedia link

 

V. smallest ring problem

  Solutions:

  It refers to find a minimum cycle in a drawing ring, so that the right side of the ring pieces of the minimum value. Floyed the same time, the way may be calculated from the smallest ring.

  The shortest path between two points is denoted dis [i] [j], g [i] [j] as an edge <i, j> weights. 

  A maximum junction ring is k (the maximum number), it is connected with two points of i, j, the shortest length of the loop g [i] [k] + g [k] [j] + (i j is the path, all node numbers are less than the path length of k).

  The following Floyed principle, the outermost loop made k-1 times, DIS [i] [j] represents the i to j path, all node numbers are smaller than the shortest path k.

  In summary, the algorithm must be able to find the smallest ring in Fig.

  code show as below:

  Reference Coder_YX 's blog

Copy the code
 void floyd(){
     int MinCost = inf;
     for(int k=1;k<=n;k++){
         for(int i=1;i<k;i++)
             for(int j=i+1;j<k;j++)
                 MinCost = min(MinCost,dis[i][j]+mp[i][k]+mp[k][j]);//更新k点之前枚举ij求经过ijk的最小环
         for(int i=1;i<=n;i++)
             for(int j=1;j<=n;j++)
                 dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);      //更新k点
     }
     if(MinCost==inf)puts("It's impossible.");
     else printf("%d\n",MinCost);
 }
Copy the code

 

About four most shortest path algorithm conclusions:

 Reference xiazdong 's blog

(1) When the value is non-negative in power, by Dijkstra.
(2) in power has a negative value, and no negative circle, with the SPFA, SPFA negative ring can be detected, but can not output negative circle.
(3) in power has a negative value, and there may be a negative ring, with the BellmanFord, it can be detected and outputs a negative circle.
(4) SPFA NEGATIVE ring: when there is a point not less than V enqueue time, the negative ring.

Guess you like

Origin www.cnblogs.com/myhnb/p/11244659.html