SPFA 是 Bellman-Ford 的佇列優化。維護 cnt[v] = 頂點 v 入隊次數。若 cnt[v] ≥ N,說明存在負環(最短路徑最多 N-1 條邊)。
struct Edge { int to, w, next; };
Edge edges[MAXE];
int head[MAXN], ecnt;
void addEdge(int u, int v, int w) {
edges[ecnt] = {v, w, head[u]};
head[u] = ecnt++;
}
bool spfa(int n) {
queue q;
vector dist(n+1, 0), cnt(n+1, 0);
vector inq(n+1, true); // 全點入隊(超級源點等價)
for (int i=1;i<=n;++i) q.push(i);
while (!q.empty()) {
int u = q.front(); q.pop(); inq[u]=false;
for (int e=head[u]; e!=-1; e=edges[e].next) {
int v = edges[e].to, w = edges[e].w;
if (dist[v] > dist[u] + w) {
dist[v] = dist[u] + w;
if (!inq[v]) {
q.push(v); inq[v]=true;
if (++cnt[v] >= n) return true; // 負環
}
}
}
}
return false;
}
addEdge(u,v,w); addEdge(v,u,w);addEdge(u,v,-w);平均 O(E),最壞 O(NE)。實際測試 POJ 3259 SPFA < 100ms,BF 矩陣版 ~1s。