Three common methods for finding the shortest path from a single source point

shortest path problem

Mainly refer to the blog:

Dijkstra : https://blog.csdn.net/qq_35644234/article/details/60870719

Floyd : https://www.jianshu.com/p/f73c7a6f5a53

SPFA:  https://blog.csdn.net/qq_35644234/article/details/61614581

Problem Description:

The weight of the edge and the smallest path from one vertex to another vertex in the graph is called the shortest path

Three commonly used algorithms:

1. Dijkstra's algorithm

Scope of application: No negative edge, because there is a negative edge, the shortest distance of a single source point of a certain point may be determined first, but a negative edge will be traversed later to make the distance shorter, thus affecting the correct answer

method:

Greedy strategy, declare an array dis to hold the shortest distance from the source point to each vertex and a collection of vertices that have found the shortest path : T

Initially, the path weight of origin s is assigned as 0 (dis[s] = 0). If there is a directly reachable edge (s, m) for vertex s, set dis[m] to w(s, m), and set the path length of all other (s unreachable) vertices to infinity. Initially, the set T has only vertex s.

Then, select the minimum value from the dis array, then the value is the shortest path from the source point s to the vertex corresponding to this value, and add this point to T, OK, then a vertex is completed, then, we need to look at the new Whether the added vertices can reach other vertices and see if the path length through this vertex to other points is shorter than the source point directly, if so, then replace the value of these vertices in dis.
Then, find the minimum value from dis, and repeat the above actions until T contains all the vertices of the graph.

Time complexity: O(V^2 + E)

The priority queue can be used to optimize the operation of selecting the point of the shortest path each time to the time complexity O((V+E) * lg V)

Implement the heap with the priority queue in STL :
while (priority queue Q(V) is not empty)
--> the head of the queue is dequeued, and its edge E is
relaxed --> the relaxed <new distance, point> is enqueued

Heap optimized code snippet:

void dijkstra() {
	vector<bool> st(n + 1);
    // 用于标记某个点是否已经在队列当中
	priority_queue<PII, vector<PII>, greater<PII>> heap;
    // 小顶堆,每次 pop 出距离最小的点
	dist[n] = 0;
	heap.push({0, n});// 进入队列
	while (heap.size()) {
		PII now = heap.top();
		heap.pop();
		int ver = now.second, distance = now.first;
		if (st[ver]) continue;// 标记该点是否已经得到了最小距离
		st[ver] = true;
		for (auto &v : g[ver]) {
			int y = v.first, w = v.second;
			if (dist[y] > distance + w) {
				dist[y] = distance + w;
				heap.push({dist[y], y});
			}
		}
	}
}

2. Floyd's algorithm

Features of the algorithm:

Freud's algorithm is an algorithm for solving the shortest path between any two points. It can correctly handle the shortest path problem of a directed graph or a directed graph or a negative weight (but no negative weight loop), and is also used for Compute the transitive closure of a directed graph.

Path output: 

Pij = k means that  the shortest path from Ai -> Aj needs to go through point k 

For the output path, it can be implemented by recursion or by stack

Time Complexity: O(N^3)

3. SPFA algorithm

Its principle is:

Perform V-1 relaxation operations on the graph to get all possible shortest paths. It is superior to the Dijkstra algorithm in that the weight of the edge can be negative and the implementation is simple . The disadvantage is that the time complexity is too high , up to O(VE). However, the algorithm can be optimized in several ways to improve efficiency.

Algorithm idea:

We use the array dis to record the shortest path estimate for each node, and use the adjacency list or adjacency matrix to store the graph G. The method we take is the dynamic approximation method: a first-in, first-out queue is set up to store the nodes to be optimized, the first node u of the queue is taken out each time during optimization, and the current shortest path estimation value of point u is used to leave point u. The node v pointed to is subjected to a relaxation operation. If the shortest path estimate value of point v is adjusted, and point v is not in the current queue, point v is placed at the end of the queue. In this way, nodes are continuously removed from the queue to perform relaxation operations until the queue is empty

We need to know that a graph with a negative cycle has no shortest path, so when we execute the algorithm, we need to determine whether the graph has a negative cycle. There are two methods:

  1. Before starting the algorithm, call topological sorting for judgment (generally not used, waste of time)
  2. A negative cycle exists if a point enters the queue more than N times (N is the number of vertices in the graph)

Each time a point in the queue is selected to update the dis array until the queue is empty

 

code show as below :

vector<bool> st(n + 1,false);// 用于记录是否在队列中
queue<int> q;
q.push(n);
while(!q.empty()) {
    int i = q.front();
    q.pop();
    st[i] = false;
    for(auto& t : g[i]) {
        int j = t.x;
        int w = t.y;
        if(min_dis[i] + w < min_dis[j]) {
            min_dis[j] = min_dis[i] + w;
            if(!st[j]) {
                q.push(j);
                st[j] = true;
            }
        }
    }
}

 

Summarize:

In general application scenarios:

If it is a dense graph, Dijkstra+heap is faster than SPFA, and if it is a sparse graph, SPFA is faster

If the shortest path is sought, SPFA+BFS is faster, and if it is negative loop detection, SPFA+DFS is faster.

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324086622&siteId=291194637