Algorithm generation notes 8 (algorithm 2 for graphs-Shortest Path Problems)

Source: Internet
Author: User

Algorithm generation notes 8 (algorithm 2 for graphs-Shortest Path Problems)

The shortest path in the figure is divided into two types: single-source shortest path problem and full-source shortest path problem. Single-source shortest path refers to the shortest distance from a single source point to all other vertices. The all-to-all shortest path problem refers to the shortest path strength problem between all vertices. In addition, there is no Faster Algorithm than the best cell algorithm to solve the single-to-nearest path problem.

I. Single-Source Shortest Path

The shortest path strength of a single source can be divided into four categories based on its weight. When the graph G = (V, E) is a no-Permission graph, the width traversal is used directly (not described here). When the weight is not negative, the Dijkstra algorithm is used. If there is a negative weight value and a negative weight ring, you can use the Bellman-Ford algorithm. The last type is the single-source shortest path of directed acyclic graph (DAG.

Dijkstra Algorithm

Dijkstra is a greedy algorithm. It is critical to prove that the greedy policy is effective.

Basic Idea: Give each vertex an estimated distance. The estimated distance of the initialization source point is 0, and the other points are infinite. The priority queue Q = V, select the vertex with the smallest Estimated distance from Q to join the set S, and then relax each edge starting from the vertex to update the estimated distance of each vertex.

It must be proved that the vertex with the Minimum Estimated distance is selected from Q and added to S. The estimated distance is equal to the shortest path of the vertex.

The Code is as follows:

// Dijkstra algorithm string Graph: intToStr (int I) {string s; stringstream ss; ss <I; ss> s; ss. clear (); return s;} void Graph: dijkstra () {mPriceQueue. clear (); mPriceQueue [0] = 0; path [0] = intToStr (0); for (int I = 1; I <vertexNum; I ++) {mPriceQueue [I] = MAXPRICE; path [I] = "";} while (! MPriceQueue. empty () {pair
 
  
PMinNode = getMinPriceVet (); // dijkstra's greedy policy is that this is the pMinNode at this time. second is the shortest path int minPriceVet = pMinNode. first; minDistance [minPriceVet] = pMinNode. second; // Save the shortest path to GNode * p = edges [minPriceVet] In minDistance. next; while (p! = NULL) {if (mPriceQueue. count (p-> val) & (p-> weight + pMinNode. second) <mPriceQueue [p-> val]) {// relaxation operation mPriceQueue [p-> val] = p-> weight + pMinNode. second; path [p-> val] = path [minPriceVet] + intToStr (p-> val);} p = p-> next ;}} // The output path for (int I = 0; I <vertexNum; I ++) {cout <"from 0 to" <I <"Shortest Path is: "<
  
   
Result:
   


Time Complexity analysis: the time complexity is the time of V * Textract min + E * Trelax. When Q is an array, the time complexity is O (V ^ 2); when Q is a binary heap, the time complexity is O (Vlg (V + E )); when Q is a fibonacci heap, the time complexity is O (VlgV + E ).

Bellman-Ford Algorithm <喎?http: www.bkjia.com kf ware vc " target="_blank" class="keylink"> Vc3ryb25np1_vcd4kpha + QmVsbG1hbi1Gb3JktcTLvM/empty + large + tqGjPC9wPgo8cD60 + large + CjxwcmUgY2xhc3M9 "brush: java; "> // BellmanFord algorithm // relaxation by edge order each edge V-1 times void Graph: bellmanFord () {minDistance [0] = 0; path [0] = intToStr (0); for (int I = 1; I <vertexNum; I ++) {minDistance [I] = MAXPRICE; Path [I] = "" ;}for (int m = 0; m <vertexNum-1; m ++) {for (int I = 0; I <vertexNum; I ++) {GNode * p = edges [I]. next; while (p! = NULL) {if (minDistance [p-> val]> p-> weight + minDistance [I]) {// relax each edge minDistance [p-> val] = minDistance [I] + p-> weight; path [p-> val] = path [I] + intToStr (p-> val);} p = p-> next ;}}for (int I = 0; I <vertexNum; I ++) {// check whether there is a negative weight loop GNode * p = edges [I]. next; while (p! = NULL) {if (minDistance [p-> val]> p-> weight + minDistance [I]) {cout <"This graph has a negative weight ring" <endl; return;} p = p-> next ;}// output path for (int I = 0; I <vertexNum; I ++) the shortest path of {cout <"from 0 to" <I <"is:" <

The result is as follows:


The time complexity is O (VE ).

Note: A difference constraint system is used here. In fact, A special case of linear planning is that each row of matrix A has only one 1 and-1, and the others are all 0. In this way, A constraint graph can be constructed, the shortest path is the solution of the differential constrained system. I will not go into details here.

Single-source shortest path of a DAG

The basic idea of the algorithm: Calculate the topological sorting of the DAG graph, then, each edge is relaxed according to the order of topological sorting vertices. That is, if d [v]> d [u] + w [u, v], then d [v] = d [u] + w [u, v]. The time complexity is O (V + E ).

Ii. All-round Shortest Path Problems

The most basic idea of finding the shortest path between all the two vertices is to apply the single-source shortest path to all the vertices. In this case, the time complexity is O (V ^ 2 + VE) when the value is not authorized) <即v*bfs> ; The weight is not negative O (V ^ 2lgV + VE) <即v*dijkstra> In general, it is O (V ^ 2 * E). In this case, for a dense image E = O (V ^ 2), it must reach O (V ^ 4, the efficiency is very low, so other algorithms are needed to improve the time complexity. There are three main methods: the first is the dynamic planning method (combined with matrix multiplication), the second is the Floyd-Warshall algorithm, and the third is the Johnson algorithm, sparse graphs are superior to the Floy-Warshall algorithm.

Dynamic Planning Method

Dijm indicates the shortest path from I to j, with a maximum of m edges passing through. At this point when m = V-1 is the shortest path we require (for a non-negative weight ring ). D (1) = W is the weight matrix. That is, evaluate D (V-1 ).

In addition, if the formula (1) is regarded as a new operation *, Every time D (m) = D (S-1) * W is obtained.

The Code is as follows:

// Use dynamic planning to obtain the full Shortest Path void Graph: dpAllDistance () {int Adj [maxSize] [maxSize]; for (int I = 0; I <vertexNum; I ++) {for (int j = 0; j <vertexNum; j ++) {minAllDistance [I] [j] = MAXPRICE; if (I = j) minAllDistance [I] [j] = 0; AllPath [I] [j] = intToStr (I ); adj [I] [j] = minAllDistance [I] [j] ;}}for (int I = 0; I <vertexNum; I ++) {GNode * p = edges [I]. next; while (p! = NULL) {minAllDistance [I] [p-> val] = p-> weight; // after passing through one edge, the weight is Adj [I] [p-> val] = p-> weight; allPath [I] [p-> val] = AllPath [I] [p-> val] + intToStr (p-> val); p = p-> next ;}} for (int m = 2; m <vertexNum; m ++) {// for (int I = 0; I <vertexNum; I ++) {for (int j = 0; j <vertexNum; j ++) {for (int k = 0; k <vertexNum; k ++) {if (minAllDistance [I] [j]> minAllDistance [I] [k] + Adj [k] [j]) {minAllDistance [I] [j] = minAllDistance [I] [k] + Adj [k] [j]; allPath [I] [j] = AllPath [I] [k] + intToStr (j );}}}}} // check whether there is a negative weight ring for (int I = 0; I <vertexNum; I ++) {if (minAllDistance [I] [I] <0) {cout <"this figure has a negative weight ring" <endl; return ;}// outputs all pairs of shortest paths for (int I = 0; I <vertexNum; I ++) {for (int j = 0; j <vertexNum; j ++) {cout <"from" <

Time Complexity: At this time, the time complexity is still O (V ^ 4), but it is calculated using D (m) = D (m/2) * D (m/2, the time complexity is O (V ^ 3 * lgV ).

Floyd-Warshall Algorithm

Defining dijk indicates that from I to j {1, 2, 3... The minimum value of all conditions that k} passes. When k = n, all vertices are taken into account, which is the shortest path.

The Code is as follows:

// Floyd-warshall Algorithm for shortest path problem void Graph: floydWarshall () {int Adj [maxSize] [maxSize]; for (int I = 0; I <vertexNum; I ++) {for (int j = 0; j <vertexNum; j ++) {minAllDistance [I] [j] = MAXPRICE; if (I = j) minAllDistance [I] [j] = 0; AllPath [I] [j] = intToStr (I ); adj [I] [j] = minAllDistance [I] [j] ;}}for (int I = 0; I <vertexNum; I ++) {GNode * p = edges [I]. next; while (p! = NULL) {minAllDistance [I] [p-> val] = p-> weight; // after passing through one edge, the weight is Adj [I] [p-> val] = p-> weight; allPath [I] [p-> val] = AllPath [I] [p-> val] + intToStr (p-> val); p = p-> next ;}} for (int k = 0; k <vertexNum; k ++) {for (int I = 0; I <vertexNum; I ++) {for (int j = 0; j <vertexNum; j ++) {if (minAllDistance [I] [j]> minAllDistance [I] [k] + minAllDistance [k] [j]) {minAllDistance [I] [j] = minAllDistance [I] [k] + minAllDistance [k] [j]; allPath [I] [j] = AllPath [I] [k] + AllPath [k] [j] ;}} // check whether there is a negative weight ring for (int I = 0; I <vertexNum; I ++) {if (minAllDistance [I] [I] <0) {cout <"this figure has a negative weight ring" <endl; return ;}// outputs all pairs of shortest paths for (int I = 0; I <vertexNum; I ++) {for (int j = 0; j <vertexNum; j ++) {cout <"from" <

The result is as follows:


The time complexity is O (V ^ 3 ).

Johnson Algorithm

The Johnson algorithm uses the weighting method. The weighted method does not change the shortest path. In addition, all weights generated by weighting are non-negative weights.

Pseudocode:


The time complexity is O (V) * Dijkstra algorithm.

All algorithm code:

Graph. h

# Ifndef GRAPH_H # define GRAPH_H # include
         
          
# Include
          
           
# Include
           # Include
            
             
# Include
             
              
Using namespace std; # define maxSize 10 # define MAXPRICE 0x10000000 // set this value to the maximum value of the weight struct GNode {int val; int weight; GNode * next ;}; class Graph {public: void createGraph (int n, int e); void destroyGraph (GNode * p );~ Graph () {for (int I = 0; I <vertexNum; I ++) {destroyGraph (edges [I]. next); // cout <"destructor:" <I <endl ;}} void showGraph (); void bfsTravel (); // void dfsTravel (); // void showTopSort (); // output the topological sequence void componentSC (); // create the void prim (), void dijkstra (), and void bellmanFord () of graph g; // dynamic programming for the full Shortest Path void dpAllDistance (); void floydWarshall (); private: int vertex [maxSize]; // store vertex GNode edges [maxSize]; // store the vertex list int vertexNum; // Number of vertex numbers int edgesNum; // Number of edge entries // bfs and dfs traverse int visited [maxSize]; void bfs (int s); void dfs (int s); int beginTime [maxSize]; // The time when the access to x starts in depth: int endTime [maxSize]; // The time when the access to x ends: static int time; vector
              
                TopSort; // the reverse order of topSort is void buildTransGraph (Graph & g) in a non-loop topological order; // create a transpose of Graph g // primmap
               
                 MPriceQueue; // Save the Minimum Spanning Tree and dijkstra algorithm cost pair
                
                  GetMinPriceVet (); int preNode [maxSize]; // used to save the edge value of the minimum spanning tree as the precursor of the node // Save the dijkstra path string path [maxSize]; // Save the final Shortest Path int minDistance [maxSize]; // Save the final minimum distance string intToStr (int I ); // save all path strengths int minAllDistance [maxSize] [maxSize]; string AllPath [maxSize] [maxSize] ;};# endif
                
               
              
             
            
          
         
Graph. cpp

# Include
         
          
# Include "graph. h" # include
          
           
# Include
           
            
Using namespace std; int Graph: time = 0; void Graph: createGraph (int n, int e) {vertexNum = n; edgesNum = e; for (int I = 0; I <n; I ++) {vertex [I] = I; edges [I]. val = I; edges [I]. weight = 0; edges [I]. next = NULL;} for (int I = 0; I <e; I ++) {int source, dest, wei; cin> source> dest> wei; GNode * newNode = new GNode (); newNode-> val = dest; newNode-> weight = wei; newNode-> next = NULL; GNode * p = & edges [source]; While (p-> next! = NULL) p = p-> next; p-> next = newNode; // The undirected graph deletes this section./* GNode * newNode2 = new GNode (); newNode2-> val = source; newNode2-> weight = wei; newNode2-> next = NULL; GNode * p2 = & edges [dest]; while (p2-> next! = NULL) p2 = p2-> next; p2-> next = newNode2; */} void Graph: destroyGraph (GNode * p) {if (p = NULL) return; else {destroyGraph (p-> next); delete p ;}} void Graph: showGraph () {for (int I = 0; I <vertexNum; I ++) {int j = I; cout <I <> "; GNode * p = edges [j]. next; while (p! = NULL) {cout <"(" <p-> val <"," <p-> weight <")"; p = p-> next;} cout <endl ;}// span traversal Graph void Graph: bfs (int s) {queue
            
             
Q; q. push (s); visited [s] = 1; while (! Q. empty () {int u = q. front (); q. pop (); cout <u <""; GNode * p = edges [u]. next; while (p! = NULL) {if (! Visited [p-> val]) {// not accessed, add it to the queue and mark it as accessed q. push (p-> val); visited [p-> val] = 1;} p = p-> next ;}} void Graph: bfsTravel () {memset (visited, 0, sizeof (int) * vertexNum); for (int I = 0; I <vertexNum; I ++) {if (! Visited [I]) {bfs (I); cout <endl ;}}// depth-first traversal void Graph: dfs (int s) {visited [s] = 1; time + = 1; beginTime [s] = time; cout <s <"(" <beginTime [s] <""; // shenGNode * p = edges [s]. next; while (p! = NULL) {if (! Visited [p-> val]) dfs (p-> val); p = p-> next;} time + = 1; endTime [s] = time; topSort. push_back (s); cout <endTime [s] <")" <"";} void Graph: dfsTravel () {memset (visited, 0, sizeof (int) * vertexNum); memset (beginTime, 0, sizeof (int) * vertexNum); // memset (endTime, 0, sizeof (int) * vertexNum); // end time of the node access for (int I = 0; I <vertexNum; I ++) {if (! Visited [I]) {dfs (I); cout <endl ;}}// output Topology Sorting void Graph: showTopSort () {for (vector
             
              
: Reverse_iterator iter = topSort. rbegin (); iter! = TopSort. rend (); iter ++) cout <* iter <"; cout <endl;} // transpose void Graph for creating Graph g :: buildTransGraph (Graph & g) {this-> vertexNum = g. vertexNum; this-> edgesNum = g. edgesNum; for (int I = 0; I <vertexNum; I ++) {this-> vertex [I] = g. vertex [I]; this-> edges [I]. val = g. edges [I]. val; this-> edges [I]. weight = g. edges [I]. weight; this-> edges [I]. next = NULL;} for (int I = 0; I <vertexNum; I ++) {GNode * p = g. edges [I]. next; w Hile (p! = NULL) {GNode * newNode = new GNode (); newNode-> val = I; newNode-> next = NULL; newNode-> weight = p-> weight; GNode * q = & edges [p-> val]; while (q-> next! = NULL) q = q-> next; q-> next = newNode; p = p-> next ;}}// void Graph: componentSC () {// time = 0; // dfsTravel (); // perform a deep search on Graph g to obtain the time required to complete x access and obtain the topological sorting Graph g2; g2.buildTransGraph (* this); // obtain the transpose time of graph G = 0; memset (g2.visited, 0, sizeof (int) * vertexNum); cout <"strongly connected component: "<endl; for (vector
              
                : Reverse_iterator iter = topSort. rbegin (); iter! = TopSort. rend (); iter ++) {// perform a deep search on the transpose graph g2 to obtain the strongly connected component if (! G2.visited [* iter]) g2.dfs (* iter) ;}cout <endl ;}// the Minimum Spanning Tree/* The Minimum Spanning Tree uses the greedy algorithm: if T is the MST (minimum spanning tree) of graph G, A belongs to V, (u, v) is an edge connecting A and V-A and has the minimum weight, then (u, v) The Edge belongs to the minimum storage cost of lowcost of the spanning tree */pair
               
                 Graph: getMinPriceVet () {pair
                
                  P; int minPrice = MAXPRICE; int minPriceVet = 0; for (map
                 
                   : Iterator iter = mPriceQueue. begin (); iter! = MPriceQueue. end (); iter ++) {if (* iter ). second <minPrice) {minPrice = (* iter ). second; minPriceVet = (* iter ). first; p = * iter;} mPriceQueue. erase (minPriceVet); // or use an array. In this case, you need to set a visited Mark array to determine whether the vertex has been added to return p;} void Graph: prim () {mPriceQueue. clear (); mPriceQueue [0] = 0; for (int I = 1; I <vertexNum; I ++) {mPriceQueue [I] = MAXPRICE;} while (! MPriceQueue. empty () {pair
                  
                    PMinNode = getMinPriceVet (); int minPriceVet = pMinNode. first; GNode * p = edges [minPriceVet]. next; while (p! = NULL) {if (mPriceQueue. count (p-> val) & p-> weight <mPriceQueue [p-> val]) {mPriceQueue [p-> val] = p-> weight; preNode [p-> val] = minPriceVet;} p = p-> next ;}// display the edge of the Minimum Spanning Tree for (int I = 1; I <vertexNum; I ++) {cout <"(" <preNode [I] <"," <I <")" ;}cout <endl ;} // dijkstra algorithm string Graph: intToStr (int I) {string s; stringstream ss; ss <I; ss> s; ss. clear (); return s;} void Graph: dijkstra () {mPriceQueue. cle Ar (); mPriceQueue [0] = 0; path [0] = intToStr (0); for (int I = 1; I <vertexNum; I ++) {mPriceQueue [I] = MAXPRICE; path [I] = "";} while (! MPriceQueue. empty () {pair
                   
                     PMinNode = getMinPriceVet (); // dijkstra's greedy policy is that this is the pMinNode at this time. second is the shortest path int minPriceVet = pMinNode. first; minDistance [minPriceVet] = pMinNode. second; // Save the shortest path to GNode * p = edges [minPriceVet] In minDistance. next; while (p! = NULL) {if (mPriceQueue. count (p-> val) & (p-> weight + pMinNode. second) <mPriceQueue [p-> val]) {// relaxation operation mPriceQueue [p-> val] = p-> weight + pMinNode. second; path [p-> val] = path [minPriceVet] + intToStr (p-> val);} p = p-> next ;}} // The output path for (int I = 0; I <vertexNum; I ++) {cout <"from 0 to" <I <"Shortest Path is: "<
                    
                      Val]> p-> weight + minDistance [I]) {// relax each edge minDistance [p-> val] = minDistance [I] + p-> weight; path [p-> val] = path [I] + intToStr (p-> val);} p = p-> next ;}}for (int I = 0; I <vertexNum; I ++) {// check whether there is a negative weight loop GNode * p = edges [I]. next; while (p! = NULL) {if (minDistance [p-> val]> p-> weight + minDistance [I]) {cout <"This graph has a negative weight ring" <endl; return;} p = p-> next ;}// output path for (int I = 0; I <vertexNum; I ++) the shortest path of {cout <"from 0 to" <I <"is:" <
                     
                       Val] = p-> weight; // after passing through one edge, the weight is Adj [I] [p-> val] = p-> weight; allPath [I] [p-> val] = AllPath [I] [p-> val] + intToStr (p-> val); p = p-> next ;}} for (int m = 2; m <vertexNum; m ++) {// for (int I = 0; I <vertexNum; I ++) {for (int j = 0; j <vertexNum; j ++) {for (int k = 0; k <vertexNum; k ++) {if (minAllDistance [I] [j]> minAllDistance [I] [k] + Adj [k] [j]) {minAllDistance [I] [j] = minAllDistance [I] [k] + Adj [k] [j]; allPath [I] [j] = AllPath [I] [k] + intToStr (j );}}}}} // check whether there is a negative weight ring for (int I = 0; I <vertexNum; I ++) {if (minAllDistance [I] [I] <0) {cout <"this figure has a negative weight ring" <endl; return ;}// outputs all pairs of shortest paths for (int I = 0; I <vertexNum; I ++) {for (int j = 0; j <vertexNum; j ++) {cout <"from" <
                      Val] = p-> weight; // after passing through one edge, the weight is Adj [I] [p-> val] = p-> weight; allPath [I] [p-> val] = AllPath [I] [p-> val] + intToStr (p-> val); p = p-> next ;}} for (int k = 0; k <vertexNum; k ++) {for (int I = 0; I <vertexNum; I ++) {for (int j = 0; j <vertexNum; j ++) {if (minAllDistance [I] [j]> minAllDistance [I] [k] + minAllDistance [k] [j]) {minAllDistance [I] [j] = minAllDistance [I] [k] + minAllDistance [k] [j]; allPath [I] [j] = AllPath [I] [k] + AllPath [k] [j] ;}} // check whether there is a negative weight ring for (int I = 0; I <vertexNum; I ++) {if (minAllDistance [I] [I] <0) {cout <"this figure has a negative weight ring" <endl; return ;}// outputs all pairs of shortest paths for (int I = 0; I <vertexNum; I ++) {for (int j = 0; j <vertexNum; j ++) {cout <"from" <

Related Article

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.