# Shortest path faster algorithm

The Shortest Path Faster Algorithm (SPFA) is an enhanced version of the Bellman–Ford algorithm that computes single-source shortest paths in a weighted directed graph. The algorithm performs optimally on sparse random graphs, particularly those with negative-weight edges. The worst-case complexity of SPFA is equivalent to that of the Bellman–Ford. Dijkstra's algorithm is preferred for graphs with nonnegative edge weights.
SPFA was first introduced by Edward F. Moore in 1959, as a generalization of the breadth-first search; SPFA is Moore's “Algorithm D.” The term “Shortest Path Faster Algorithm (SPFA)” was coined by Fanding Duan, a Chinese researcher who rediscovered the algorithm in 1994.

## Algorithm

Given a weighted directed graph $G=(V,E)$ and a source vertex $s$, SPFA determines the shortest path from $s$ to each vertex $v$ in the graph. The length of the shortest path from $s$ to $v$ is stored in $d(v)$ for each vertex $v$.
SPFA improves upon the Bellman-Ford algorithm by selectively using vertices to relax their adjacent vertices. Instead of processing all vertices indiscriminately, SPFA maintains a queue of candidate vertices and only adds a vertex to the queue if it has been relaxed, continuing this process until no further vertices can be relaxed.
Below is the pseudocode for the algorithm. Here $Q$ is a first-in, first-out queue of candidate vertices, and $w(u,v)$ is the edge weight between $(u,v)$.
The algorithm can also be applied to an undirected graph by treating each undirected edge as two directed edges of opposite directions.

## Proof of correctness

It is feasible to demonstrate that the algorithm consistently identifies the shortest path.
    Lemma: Whenever the queue is checked for emptiness, any vertex capable of causing relaxation is in the queue.
    Proof: To demonstrate that if $dist[w]>dist[u]+w(u,w)$ for any two vertices $u$ and $w$ when the condition is checked, $u$ is in the queue. We use induction based on the number of iterations of the loop that have occurred. Initially, this holds before the loop starts: If $u\not =s$, then relaxation is not possible; relaxation is possible from $u=s$, and this vertex is added to the queue immediately before the while loop begins. Inside the loop, a vertex $u$ is popped and used to relax all its neighbors, if possible. Immediately after that iteration of the loop, $u$ is not capable of causing any more relaxations (and does not need to be in the queue anymore). However, the relaxation by $x$ might cause some other vertices to become capable of causing relaxation. If there exists some vertex $x$ such that $dist[x]>dist[w]+w(w,x)$ before the current loop iteration, then $w$ is already in the queue. If this condition becomes true during the current loop iteration, then either $dist[x]$ increased, which is impossible, or $dist[w]$ decreased, implying that $w$ was relaxed. But after $w$ is relaxed, it is added to the queue if it is not already present.
    Corollary: The algorithm terminates when and only when no further relaxations are possible.
    Proof: If no further relaxations are possible, the algorithm continues to remove vertices from the queue but does not add any more to the queue, because vertices are added only upon successful relaxations. Therefore, the queue becomes empty and the algorithm terminates. If any further relaxations are possible, the queue is not empty, and the algorithm continues to run.
The algorithm fails to terminate if negative-weight cycles are reachable from the source. See here for proof that relaxations are always possible when negative-weight cycles exist. In a graph with no cycles of negative weight, when no more relaxations are possible, the correct shortest paths have been computed (proof). Therefore, in graphs containing no cycles of negative weight, the algorithm will never terminate with incorrect shortest path lengths.

## Complexity

Experiments indicate that the average time complexity of SPFA is $O(|E|)$ on random graphs, and the worst-case time complexity is $\Omega (|V|\cdot |E|)$, which is equal to that of the Bellman-Ford algorithm.

## Optimization techniques

The performance of the algorithm is significantly influenced by the order in which candidate vertices are used to relax other vertices. Although $Q$ is not a priority queue, two techniques are often used to enhance the quality of the queue, thereby improving the average-case performance (but not the worst-case performance). Both techniques reorder the elements in $Q$ so that vertices closer to the source are processed first. Therefore, when implementing these techniques, $Q$ is no longer a first-in, first-out (FIFO) queue, but rather a normal doubly linked list or double-ended queue.
Small Label First (SLF) technique:
In line 11 of the above pseudocode, instead of always pushing the vertex $v$ to the end of the queue, we compare $d(v)$ to $d{\big{\text{front}}(Q){\big )}$, and insert $v$ to the front of the queue if $d(v)$ is smaller. The pseudo-code for this technique is (after pushing $v$ to the end of the queue in line 11):
Large Label Last (LLL) technique:
After line 11, we update the queue so that the first element is smaller than the average, and any element larger than the average is moved to the end of the queue. The pseudo-code is: