Shortest Path Faster Algorithm — a queue-based refinement of Bellman-Ford that only relaxes edges out of vertices whose distance actually changed. Fast on typical graphs, in the worst case.

vector<long long> spfa(int n, int s, vector<vector<pair<int,int>>>& adj) {
    const long long INF = LLONG_MAX / 4;
    vector<long long> dist(n, INF);
    vector<int> inQueue(n, 0), cnt(n, 0);
    deque<int> q;
 
    dist[s] = 0; q.push_back(s); inQueue[s] = 1;
    while (!q.empty()) {
        int u = q.front(); q.pop_front();
        inQueue[u] = 0;
        for (auto [v, w] : adj[u])
            if (dist[u] + w < dist[v]) {
                dist[v] = dist[u] + w;
                if (!inQueue[v]) {
                    if (++cnt[v] > n) return {};      // negative cycle
                    q.push_back(v); inQueue[v] = 1;
                }
            }
    }
    return dist;
}

The inQueue flag is what makes it faster than plain Bellman-Ford: a vertex already waiting to be processed is not queued twice.

Negative cycle detection

Count how many times each vertex is enqueued. If any vertex enters the queue more than times, a negative cycle is reachable from the source. (Counting relaxations along a path — tracking the number of edges on the current best path and failing at — is a slightly stronger and equally cheap check.)

Why it can be hacked

SPFA is not safe on Codeforces

The worst case is , and adversarial graphs that force it are well known and easy to generate. Problem setters routinely include anti-SPFA tests. It has been a running joke since the blog post titled “SPFA is dead” — do not submit plain SPFA on a problem where would TLE.

Mitigations that help but do not fix the worst case:

  • SLF (Small Label First). Before pushing , if dist[v] < dist[q.front()], push to the front instead of the back. This is a generalisation of 0-1 BFS’s deque trick.
  • LLL (Large Label Last). Keep rotating the front to the back while dist[front] > average(dist in queue).
  • Both together (SLF+LLL) are the common “optimised SPFA”, and both are still hackable.

When to actually use it

SituationUse
Non-negative weightsDijkstra — never SPFA
Negative weights, need a guaranteeBellman-Ford
All-pairs with negatives, sparseJohnson
Min-cost flow inner loopBellman-Ford once for potentials, then Dijkstra
Difference constraintsBellman-Ford (or SPFA if the graph is random-ish and is safe)

SPFA’s honest niche is difference-constraint systems and small graphs with negative weights, where its practical speed is convenient and its worst case is still within the limit.

Difference constraints

A system of constraints becomes a graph with edge of weight . Shortest paths from a super-source connected to everything with weight 0 give a feasible assignment; a negative cycle means the system is infeasible. This is the main reason to keep a negative-weight shortest path algorithm in your toolkit at all.

See also: Bellman-Ford · Negative Cycles · Shortest Paths