Graph theory (ii): Four shortest path algorithms for graphs

Source: Internet
Author: User

This paper summarizes the realization of several shortest path algorithms of graphs: depth or Breadth First search algorithm, Freud algorithm, Dijkstra algorithm, Bellman-ford algorithm


1), depth or breadth First search algorithm (solve single source shortest path)
To access all depth traversal paths or breadth-first paths from the starting node, the path to the endpoint node is multiple, and the shortest path is the shortest one.

Here's the core code:

void Dfs (int cur, int dst) {      /***operation***/        /***operation***/      if (Minpath < DST) return;// The current path is greater than the shortest path before, there is no need to go down      if (cur = = N) {//Critical condition          if (Minpath > DST) minpath = DST;          return;      }      else{          int i;          for (i = 1; I <= n; i++) {              if (edge[cur][i]! = INF && edge[cur][i]! = 0 && Mark[i] = = 0) {                  mark[i ] = 1;                  DFS (i, dst+edge[cur][i]);                  Mark[i] = 0;  You need to set the access flag at 0}} return when the depth traversal is returned          ;}  }  
Example 1: The following is a map of the city, note is a one-way map, the City 1 to the shortest distance from the City 5. (referring to the last summarized figure theory (i) in 1) Example 2)

/*** first input n nodes, M edge, then input to the M edge of the graph, the first two elements of the edge represents the starting node, the third Value table weights, the output of city 1th to the shortest distance to the city of N ***//*** algorithm is to access all the deep traversal path, you need to return the depth of the visit flag 0**  */#include <iostream> #include <iomanip> #define NMAX #define INF 999999999 using namespace std; int n, m, Minpath, Edge[nmax][nmax], mark[nmax];//node, number of sides, minimum path, adjacency matrix, node access mark void Dfs (int cur, int dst) {/***operation* **//***operation***/if (Minpath < DST) return;//current traversed path is greater than previous shortest path, no need to go further if (cur = = N) {//Critical condition I          F (Minpath > DST) minpath = DST;      Return          } else{int i;                  for (i = 1; I <= n; i++) {if (Edge[cur][i]! = INF && edge[cur][i]! = 0 && Mark[i] = = 0) {                  Mark[i] = 1;                  DFS (i, dst+edge[cur][i]);                          Mark[i] = 0;      }} return;          }} int main () {while (CIN >> n >> m && n! = 0) {//initialize adjacency matrix int i, J; for (i = 1; I <= n; i+ +) {for (j = 1; J <= N; j + +) {Edge[i][j] = inf;          } Edge[i][i] = 0;          } int A, b;              while (m--) {cin >> a >> b;          CIN >> Edge[a][b];          }//Starts with DNF (1) as the starting point for recursive traversal of memset (mark, 0, sizeof (Mark));          Minpath = inf;          MARK[1] = 1;          DFS (1, 0);      cout << Minpath << Endl;  } return 0;   }
The results of the program run as follows:



2), Freud algorithm (solve multi-source shortest path): Time complexity O (n^3), Space complexity O (n^2)
Basic idea: The first only allowed to go through the 1th vertex for the relay, and then only allowed to pass through the vertices of number 1th and 2nd. Allows all vertices of the 1~n to be brokered to dynamically update the shortest distance between any two points. That is, the shortest distance from the vertex of I to the J Vertex is only past the first K point.

The analysis is as follows:1, first constructs the adjacency matrix floyd[n+1][n+1], if now only allows through 1th number junction, asks any two points between the shortest distance, obviously floyd[i][j] = Min{floyd[i][j], floyd[i][1]+ FLOYD[1][J]}, the code is as follows:

for (i = 1; I <= N, i++) {for (j = 1; J <= N; j + +) {if (Floyd[i][j] > Floyd[i][1] + floyd[1][j]) floyd[i][j] = Floyd[i] [1] + floyd[1][j];}}
2, the next step is to allow only 1 and 2nd two vertices in the case of the shortest distance between any two points, in the implementation has been achieved from vertex I to J Vertex only through the first 1th points of the shortest route, now insert the 2nd node, to see if we can update the shorter path, So only in step 1 to obtain the floyd[n+1][n+1] based on floyd[i][j] = Min{floyd[i][j], floyd[i][2]+floyd[2][j]};
3, It is obvious that you need n times such an update, indicating that the insertion of number 1th, number 2nd .... n Junction, the last floyd[n+1][n+1] is the shortest distance from the vertex of I to the J vertex only through the first n points. So the core code is as follows:

#define INF 99999999for (k = 1; k <= N; k++) {for (i = 1, i <= N; i++) {for (j = 1; J <= N; j + +) {if (Floyd[i][k] < I NF && Floyd[k][j] < inf && floyd[i][j] > Floyd[i][k] + floyd[k][j]) floyd[i][j] = Floyd[i][k] + Floyd K [j];}}}
Example 1: Find the shortest route from the store to the arena. Where the store at the junction of 1th, the stadium at the N Junction, 1~n junction with M-line two-way connection.

/*** first input n,m, and then input m three triples, N for the intersection number, m means there are several roads where 1 is a store, N for the arena, ternary Group table starting point, end, the path is long, output 1 to n Shortest path ***/#include <iostream>using namespace std; #define INF 99999999#define Nmax 110int Edge[nmax][nmax], N, m;int main () {while (CIN >> n >> M &A mp;& n!= 0) {//build adjacency matrix int i, j;for (i = 1; I <= n; i++) {for (j = 1; J <= N; j + +) {Edge[i][j] = inf;} Edge[i][i] = 0;} while (m--) {cin >> i >> j;cin >> edge[i][j];edge[j][i] = edge[i][j];} Use Freud algorithm int k;for (k = 1; k <= N; k++) {for (i = 1; I <= n; i++) {for (j = 1; J <= N; j + +) {if (Edge[i][k] < inf &A mp;& Edge[k][j] < inf && edge[i][j] > Edge[i][k] + edge[k][j]) edge[i][j] = Edge[i][k] + edge[k][j];}}} cout << Edge[1][n] << Endl;} return 0;}
The results of the program run as follows:



3), Dijkstra algorithm (solve single source shortest path)
Basic idea: Each time you find a vertex closest to a source point (such as a 1th node), then expand it centered on that vertex, and finally get the shortest path from the source point to all the remaining points.
Basic steps:1, set tag array book[]: divides all vertices into two parts, the vertex set p of the shortest path known and the vertex set of the unknown shortest path Q, it is obvious that the first collection P has only one vertex of the source point. Book[i] for 1 is expressed in the set P;
2, set the shortest path array dst[] and constantly update: in the initial state, make dst[i] = Edge[s][i] (s is the source point, Edge is the adjacency matrix), it is clear that this time dst[s]=0,book[s]=1. At this point, you can select a nearest vertex from the source point s in the set Q to join to P. And according to the new center point of u, the relaxation operation of each edge (relaxation refers to the way from the node s-->j can go through point u, and make dst[j]=min{dst[j], Dst[u]+edge[u][j]}), and make book[u]=1;
3, in the set Q again select a distance from the source point s nearest vertex v added to p. And according to the new center point of V, the relaxation operation of each edge (ie dst[j]=min{dst[j], dst[v]+edge[v][j]}) and the book[v]=1;
4, repeat 3 until the set Q is empty.
Here is the illustration:

The core code is as follows:

#define INF 99999999/*** constructs the adjacency matrix edge[][], and 1 is the source point ***/for (i = 1; I <= n; i++) Dst[i] = edge[1][s];for (i = 1; I <= n; i++) Book[i] = 0;book[1] = 1;for (i = 1; I <= n-1; i++) {//finds the nearest vertex u from the source point, which is called the new center point min = inf;for (j = 1; J <= N; j + +) {if (Book[j] = = 0 && dst[j] < min) {min = Dst[j];u = j;}} BOOK[U] = 1;//Update Shortest path array for (k = 1; k <= N; k++) {if (Edge[u][k] < inf && Book[k] = = 0) {if (Dst[k] > Dst[u] + E DGE[U][K]) dst[k] = Dst[u] + edge[u][k];}}
Example 1: give you n points, M without the edge, each side has a length D and spend P, give you the starting point S, the end point T, the minimum distance from the output starting point to the end point and its cost, if the shortest distance has more than one route, the output cost is the least.
Input: Enter N,m, the number of the point is 1~n, then the M line, 4 numbers per line a,b,d,p, indicates that A and B have an edge, and its length is D, the cost is P. The last line is two numbers s,t; start s, end point T. N and m are 0 o'clock input end. (1<n<=1000, 0<m<100000, s! = t)
Output: Output one line, there are two numbers, the shortest distance and its cost.
Analysis: Because each side has a length D and spend P, it is best to build the edge structure of the storage, in addition to the use of adjacent linked lists, the use of adjacent linked list when the above core code needs to be modified several places:

1, initialize dst[] When using node 1 adjacency linked list;
2, when updating the shortest path array, the range of K is changed from 1~n to 1~edge[u].size (). Using the adjacency matrix to solve the problem, and then use the adjacency table to solve the problem, the two methods are the same: Initialize the adjacency matrix or adjacency linked list, and
Initialize the shortest path array DST----> n-1 wheel Edge Relaxation, first find the closest to the new source point U, and then update the path array according to the center point U as a turning point.

To solve using adjacency matrices:

/*** in the case of an n,m, the number of points is 1~n, then the M line, and 4 a,b,d,p per line, indicating an edge between A and B, with a length of D and a cost of p. The last line is two numbers s,t; start s, end point T. N and m are 0 o'clock input end. (1<n<=1000, 0<m<100000, s! = t) output: Output one line, there are two numbers, the shortest distance and its cost. /#include <iostream> #include <iomanip>using namespace std, #define NMAX 1001#define inf 99999999struct Edge{int len;int cost;}; Edge Edge[nmax][nmax];int Dst[nmax], Spend[nmax], Book[nmax], N, M, Stnode, Ennode;int main () {while (CIN >> N >&gt ; M && n! = 0 && m! = 0) {int A, B, I, j;//constructs adjacency matrix and Shortest path array for (i = 1; I <= n; i++) {for (j = 1; J <= N; j + +) {edge[i][j].cost = 0;edge[i][j].len = inf;} Edge[i][i].len = 0;} while (m--) {cin >> a >> b;cin >> edge[a][b].len >> edge[a][b].cost;edge[b][a].len = edge[a][b]. Len;edge[b][a].cost = Edge[a][b].cost;} CIN >> Stnode >> ennode;for (i = 1; I <= n; i++) {dst[i] = edge[stnode][i].len;spend[i] = Edge[stnode][i].cos t;} memset (book, 0, sizeof); Book[stnode] = 1;//begins Dijkstra algorithm, and makes the remaining n-1 times slack int k;for (k = 1;K <= n-1;  k++) {//Find nearest vertex uint Minnode from source point, Min = inf;for (i = 1; I <= n; i++) {if (book[i] = = 0 && min > dst[i]/* | min = = dst[i]&& edge[stnode][min].cost > edge[stnode][i].cost*/) {min = Dst[i];minnode = i;}} cout << SETW (2) << Minnode;book[minnode] = 1;//Easy Error 1, mistakenly written book[i]=1//with center point U as a turning point to update path array and spend array for (i = 1; I <= n ; i++) {if (book[i] = = 0 && dst[i] > Dst[minnode] + edge[minnode][i].len | | dst[i] = = Dst[minnode] + edge[minnode][ I].len && Spend[i] > Spend[minnode] + edge[minnode][i].cost) {Dst[i] = Dst[minnode] + edge[minnode][i].len;// Easy wrong point 2, wrong written dst[i]+spend[i] = Spend[minnode] + edge[minnode][i].cost;}}} cout << Dst[ennode] << setw (3) << Spend[ennode] << Endl;} return 0;}
The results of the program run as follows:



Solve using adjacency list:

/*** in the case of an n,m, the number of points is 1~n, then the M line, and 4 a,b,d,p per line, indicating an edge between A and B, with a length of D and a cost of p. The last line is two numbers s,t; start s, end point T. N and m are 0 o'clock input end. (1<n<=1000, 0<m<100000, s! = t) output: Output one line, there are two numbers, the shortest distance and its cost. /#include <iostream> #include <iomanip> #include <vector>using namespace std; #define NMAX 1001# Define INF 99999999struct Edge{int len;int cost;int next;}; Vector<edge> Edge[nmax];int Dst[nmax], Spend[nmax], Book[nmax], N, M, Stnode, Ennode;int main () {while (CIN >> n >> m && n! = 0 && m! = 0) {int A, B, I, j;//constructs adjacency table and Shortest path array for (i = 1; I <= n; i++) edge[i].clear (); while (m--) {Edge tmp;cin >> a >> b;tmp.next = b;cin >> tmp.len >> tmp.cost;edge[a].push_back (TMP); Tmp.next = A;edge[b].push_back (TMP);} CIN >> Stnode >> ennode;for (i = 1; I <= n; i++) dst[i] = inf; Note 2, do not forget to write this sentence to initialize dst[]for (i = 0; i < edge[stnode].size (); i++) {//note 1, starting from subscript 0 to save the element, mistakenly written as I <= edge[stnode].size () dst[ Edge[stnode][i].next] = edge[stnode][i].len;//cout << dst[2] << endl;spend[edge[stnode][i].next] = edge[stnode][i].cost;} memset (book, 0, sizeof); Book[stnode] = 1;//begins Dijkstra algorithm, carries out the remaining n-1 times relaxation int k;for (k = 1; k <= n-1; k++) {//Find the closest vertex uint mi of the source point) Nnode, min = inf;for (i = 1; I <= n; i++) {if (book[i] = = 0 && min > dst[i]/* | min = = dst[i]&& edge[ Stnode][min].cost > edge[stnode][i].cost*/) {min = Dst[i];minnode = i;}} cout << SETW (2) << Minnode;book[minnode] = 1;//Easy error 1, wrong write book[i]=1//with center point U as turning point to update path array and spend array for (i = 0; i < Ed Ge[minnode].size (); i++) {int t = edge[minnode][i].next;//do not forget to add this sentence, indicating that the point minnode adjacent to the node if (book[t] = = 0 && dst[t] > Dst[minnode] + edge[mi Nnode][i].len | | Dst[t] = = Dst[minnode] + edge[minnode][i].len && spend[t] > Spend[minnode] + edge[minnode][i].cost) {Dst[t] = ds T[minnode] + edge[minnode][i].len;spend[t] = Spend[minnode] + edge[minnode][i].cost;}}} cout << Dst[ennode] << setw (3) << Spend[ennode] << Endl;} return 0;}
The results of the program run as follows:


When using adjacency tables, be aware that the adjacency TABLE element corresponds to the next member in the subscript when updating dst[],book[], while the weighted value plus and minus times need to use the corresponding subscript in the adjacency table to obtain the weights, while the adjacency matrix is not so much to worry about, because the adjacency matrix corresponds to subscript and dst[] The index of the element to update is exactly the same, starting with 1 numbering.



4), Bellman-ford algorithm (solve the negative right side, solve the single source shortest path, the previous methods can not find a negative right side of the graph):: Time complexity O (nm), Space complexity O (m)
Main idea: n-1 wheel slack operation on all edges, because in a graph with n vertices, the shortest path between any two points contains up to n-1 edges. In other words, after the 1th round is relaxed on all sides, the shortest path length from vertex 1th to the rest of the points can only be reached by one edge. After the 2nd round is relaxed on all sides, the shortest path length from vertex 1th to the remaining points can only be reached by two sides.
Here is the illustration:


In addition, Bellman_ford can also detect whether a graph contains a negative weight loop: if there is still dst[e[i] > dst[s[i]]+w[i after n-1 wheel relaxation). The algorithm core code is as follows:

#define INF 999999999for (i = 1; I <= n; i++) dst[i] = inf;dst[1] = 0;for (k = 1; k <= n-1; k++) {for (i = 1; I <= m; i++) {if (Dst[e[i]] > Dst[s[i]] + w[i]) dst[e[i] [= dst[s[i]] + w[i];}} Detect negative weight loop flag = 0;for (i = 1; I <= m; i++) {if (Dst[e[i]] > Dst[s[i]] + w[i]) flag = 1;} if (flag) cout << "This graph contains a negative power loop";
Example 1: A graph with negative weights in the diagram, the output from the node 1 to the shortest path of the nodes, and to determine whether there is no negative power loop.

/*** first enter N,m , the table nodes and the number of sides, followed by the input m three triples, the beginning of each table, the end, edge, the output of 1th nodes to the shortest path to each node ****/#include <iostream> #include <iomanip>using namespace std; #define NMAX 1001#define inf 99999999int N, M, S[nmax], E[nmax], W[nmax], Dst[nmax];int main () {while (CIN  ;> n >> m && n! = 0 && m! = 0) {int I, j;//initialize three arrays: start of array s[], endpoint array e[], weight array w[], Shortest path array dst[]for (i = 1; i <= m; i++) cin >> S[i] >> e[i] >> w[i];for (i = 1; I <= n; i++) dst[i] = inf;dst[1] = 0;//use Bellman_ford algorithm for ( j = 1; J <= N-1; J + +) {for (i = 1; I <= m; i++) {if (Dst[e[i]] > Dst[s[i]] + w[i]) dst[e[i]] = dst[s[i] [+ W[i];}} Test if there is a negative weight loop and output int flag = 0;for (i = 1; I <= m; i++) if (Dst[e[i]] > Dst[s[i]] + w[i]) flag = 1;IF (flag) cout << "this The graph contains a negative weight loop \ n "; else{for (i = 1; I <= n; i++) {if (i = = 1) cout << dst[i];else cout << setw (3) << dst[i];} cout << Endl;}} return 0;} 
The results of the program run as follows:






Graph theory (ii): Four shortest path algorithms for graphs

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.