Dijkstra algorithm:
Solved problems:
The shortest path of a single source in a weighted directed graph. And the weight is not negative. If the implementation method is appropriate, the running time of Dijkstra is lower than that of the Bellman-Ford algorithm.
Ideas:
If there is a shortest path (Vi... VK, vj) from I to J, VK is a vertex before VJ. Then (Vi... VK) must be the shortest path from I to K. In order to find the shortest path, Dijkstra proposed an algorithm to generate the Shortest Path progressively with the shortest path length. For example, for Source Vertex v0, first select the vertex VI with the shortest length in its directly adjacent vertex, the shortest distance from V0 to vj vertex is known as Dist [J] = min {Dist [J], DIST [I] + matrix [I] [J]}. the greedy idea is applied. Based on this idea, the pseudocode of the Dijkstra algorithm is provided directly. It can be used to calculate the single-source shortest path of the positive weight graph and is applicable to undirected graphs and Directed Graphs.
Clear the labels of all vertices
Set d [0] = 0, other d [I] = inf
Loop n times
{
Select the node X with the smallest D value from the labels of all vertices.
Mark node x
For all edges (x, y) starting from X, update d [y] = min {d [Y], d [x] + W (x, y )}
}
In addition to finding the maximum short-circuit length, the Dijkstra algorithm can also easily print the shortest path from node 0 to all nodes.
Code implementation:
Void Dijkstra (INT start) // start from the start point {int I, j, k; memset (VIS, 0, sizeof (VIS )); // mark whether the for (I = 1; I <= N; I ++) is accessed. // n indicates the total number of points {if (I = Start) dis [I] = 0; else dis [I] = inf;} for (I = 1; I <= N; I ++) {int R; int min = inf; for (j = 1; j <= N; j ++) if (! Vis [J] & dis [J] <min) {min = dis [J]; r = J;} vis [R] = 1; for (k = 1; k <= N; k ++) // relax all edges starting from R if (DIS [k] <(DIS [R] + G [r] [k]) dis [k] = dis [k]; else dis [k] = dis [R] + G [r] [k];} return ;}
Floyd algorithm:
An edge with a negative weight can exist, but a loop with a negative weight cannot exist.
The algorithm considers the intermediate node on a shortest path.
Core Idea of algorithms: Three-Ring for Loop
For (int K = 0; k <graph. getnumvex (); k ++) {for (int v = 0; v <graph. getnumvex (); V ++) {for (int w = 0; W <graph. getnumvex (); W ++) {If (d [v] [W]> d [v] [k] + d [k] [W]) {d [v] [W] = d [v] [k] + d [k] [W]; P [v] [W] = P [v] [k]; // P [v] [W] is the next vertex of V in the V -- w Shortest Path }}}}
The first K is used as the intermediate vertex.
Layer 2 V is the starting vertex.
Layer 3 W is used as the destination Vertex
Inner Core code:
Start with V, W, and then use K as the center point between V and W, determine the size relationship between D [v] [W] And d [v] [k] + d [k] [W, if d [v] [W]> d [v] [k] + d [k] [W], the shorter path from V to W is found, change the value of d [v] [W] to d [v] [k] + d [k] [W].
Change the value of P [v] [W] to the value of P [v] [K, because the value of P [v] [k] is the successor vertex of V in the V → k Shortest Path, and the V → W Shortest Path is connected to the V → K path, therefore, P [v] [W] must also point to P [v] [K].
NOTE: For the K-cycle in the outermost layer, the result of the N-cycle is closely related to the error process in the n + 1 loop,
After the three cycles are completed, the shortest path weights between vertices are stored in the D matrix. d [I] [J] indicates the Shortest Path weights of I → J.
Implementation of the adjacent matrix algorithm:
void Floyd(MGraph g){ int A[MAXV][MAXV]; int path[MAXV][MAXV]; int i,j,k,n=g.n; for(i=0;i<n;i++) for(j=0;j<n;j++) { A[i][j]=g.edges[i][j]; path[i][j]=-1; } for(k=0;k<n;k++) { for(i=0;i<n;i++) for(j=0;j<n;j++) if(A[i][j]>(A[i][k]+A[k][j])) { A[i][j]=A[i][k]+A[k][j]; path[i][j]=k; } } }
Bellman-Ford Algorithm
Solved problems:
In general, the single-source shortest path problem, where the weight can be negative.
The bellman-Ford algorithm returns a Boolean value. 1 indicates whether a loop with a negative weight can be obtained from the source node. If such a loop exists, the algorithm will tell us that there is no solution. If there is no such loop, the algorithm will give the shortest path and their weight.
The flow of the Bellman-Ford algorithm is as follows:
Given graph G (V, E) (where V and E are vertex sets and edge sets of graph G respectively), Source Vertex s, array distant [I] records the path length from the source point S to the vertex I. The initialized array distant [N] is, and distant [s] is 0;
The following operations can be performed cyclically for up to n-1 times, and N is the number of vertices:
For each edge e (u, v), if distant [u] + W (u, v) <distant [v], then distant [v] = distant [u] + W (u, v ). W (u, v) is the weight of edge e (u, v;
If the preceding operation does not update distant, it indicates that the shortest path has been searched, or some vertices are not reachable. Otherwise, execute the next loop;
To check whether a negative loop exists in the graph, that is, the loop with the sum of weights less than 0. For each edge e (u, v), if there is an edge of distant [u] + W (u, v) <distant [v], there is a negative loop in the figure, that is, the shortest path of a single source cannot be obtained by modifying the image. Otherwise, the shortest path length from the Source Vertex s to each vertex is recorded in the array distant [N.
We can see that the time complexity of the Bellman-Ford Algorithm for Finding the single-source shortest path is O (V * E ).
The bellman-Ford algorithm can be roughly divided into three parts:
First, Initialize all vertices. Save a value for each vertex, indicating the distance from the origin to this vertex. Set the value of the origin to 0, and set the value of other vertices to infinity (indicating that the origin cannot be reached ).
Second, perform a loop. The subscripts of the loop are from 1 to n-1 (N is equal to the number of vertices in the graph ). In the loop, traverse all edges for relaxation calculation.
Third, traverse all the edges (u, v) on the way to determine whether such a situation exists:
D (v)> d (u) + W (u, v)
The return value is false, indicating that there is a loop with a negative permission from the source point.
The reason for the third part is that if there is a loop with the right to reach from the source point as negative. Therefore, the shortest path cannot be obtained because it cannot be converged.
# Include <iostream> # include <cstdio> using namespace STD; # define Max 0x3f3f3f # define n 1010int nodenum, edgenum, original; // vertex, edge, start Point typedef struct edge // edge {int U, V; int cost;} edge; edge [N]; int dis [N], pre [N]; bool bellman_ford () {for (INT I = 1; I <= nodenum; ++ I) {if (I = original) dis [I] = 0; else dis [I] = max;} For (INT I = 1; I <= nodenum-1; ++ I) // cyclically n-1 times for (Int J = 1; j <= edgenum; ++ J) // traverse each edge {If (DIS [edge [J]. V]> dis [edge [J]. u] + edge [J]. Cost) // relaxation (the order must not be reversed ~) {Dis [edge [J]. v] = dis [edge [J]. u] + edge [J]. cost; printf ("% d", DIS [edge [J]. v]); Pre [edge [J]. v] = edge [J]. u;} printf ("% d", DIS [edge [J]. v]);} bool flag = 1; // determines whether a negative loop for (INT I = 1; I <= edgenum; ++ I) exists) if (DIS [edge [I]. v]> dis [edge [I]. u] + edge [I]. cost) {flag = 0; break;} return flag;} void print_path (INT root) // print the shortest path (reverse) {While (root! = Pre [root]) // precursor {printf ("% d -->", root); root = pre [root];} If (root = pre [root]) printf ("% d \ n", root);} int main () {scanf ("% d", & nodenum, & edgenum, & original ); pre [original] = original; For (INT I = 1; I <= edgenum; ++ I) {scanf ("% d ", & edge [I]. u, & edge [I]. v, & edge [I]. cost);} If (bellman_ford () for (INT I = 1; I <= nodenum; ++ I) // The shortest path of each vertex {printf ("% d \ n", DIS [I]); printf ("Path:"); print_path (I );} else printf ("have negative circle \ n"); Return 0 ;}
Spfa algorithm:
Algorithm flow
The general process of an algorithm is to use a queue for maintenance. Initially, the source is added to the queue. Each time an element is extracted from the queue and all neighboring points are relaxed. If a neighboring point is relaxed successfully, it is added to the queue. The algorithm ends when the queue is empty.
This algorithm, simply put, is the Bellman-Ford of queue optimization, which was invented using the features that each vertex does not update too many times.
Spfa -- Shortest Path faster algorithm, which can find the shortest path from the source point to all other points in the time complexity of O (KE) and process the negative edge. The implementation of spfa is even simpler than Dijkstra or bellman_ford:
Set DIST to represent the current shortest distance from S to I, and FA to represent the number of a vertex before I in the current shortest path from S to I. At the beginning, DIST is all + ∞, only Dist [s] = 0, and FA is all 0.
Maintain a queue that stores all vertices that need to be iterated. Initially, the queue only has one vertex S. Use a Boolean array to record whether each vertex is in a queue.
In each iteration, retrieve the vertex v in the head of the team, enumerate the edges V-> U starting from V in sequence, and set the edge length to Len, determine whether Dist [v] + Len is smaller than Dist [u]. If it is smaller than Dist [u], improve Dist [u] and Mark Fa [u] AS v, and because the shortest distance from S to u decreases, it is possible that u can improve other points. If U is not in the queue, put it at the end of the team. In this way, the iteration continues until the queue becomes empty, that is, the shortest distance from S to all is determined to end the algorithm.If a node has more than N queues, a negative weight ring exists..
The form of spfa is very similar to the width-first search. The difference is that the queue cannot be re-entered when a vertex in the width-first search, however, a point in spfa may be put into the queue again after the queue is out, that is, after a point is improved by another point, it may be improved after a period of time, so it is used again to improve other points, so that iteration continues. Set a vertex to improve other vertices by K on average. It can be proved that K is about 2 in general cases.
Code Template:
Spfavoid spfa () {for (int I (0); I <num_town; ++ I) // initialize {dis [I] = max; visited [I] = false ;} queue <int> q; DIS [start] = 0; visited [start] = true; q. push (start); While (! Q. empty () {int temp = Q. front (); q. pop (); For (int I (0); I <num_town; ++ I) {If (DIS [temp] + road [temp] [I] <dis [I]) // if there is a negative weight, you need to create a count array, if the number of times of joining a vertex exceeds V (number of vertices), return. {Dis [I] = dis [temp] + road [temp] [I]; If (! Visited [I]) {q. Push (I); visited [I] = true ;}} visited [temp] = false ;}}
After summing up the four algorithms, they all work together, and they are not good at learning. Let's just calm down and learn well. One day, you may find that the days are very difficult. It may be that this harvest will be very huge. I have been complaining about my life these days, but I forgot why I stayed for summer training. Because you have nothing, you must work hard! Xiaowei !~ Fuel
---- Anonymous. pjq