[算法] SPFA算法LLL优化和SLF优化

前言

\(SPFA\) 通常在稀疏图中运行效率高于 \(Dijkstra\) ,但是也容易被卡。

普通的 \(SPFA\) 时间复杂度为 \(O(km)\) ,其中 \(k\) 是一条边松弛其端点点的次数,是一个较小的常数。

但是对于特殊构造的图中也会退化到 \(O(nm)\) ,这就与 \(Bellman-Ford\) 一样。

对此部分情况,可使用 \(SLF\)\(LLL\) 优化 \(SPFA\)

C++代码

#include <queue>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
#define INF 0x3f3f3f3f
void Quick_Read(int &N) {
	N = 0;
	int op = 1;
	char c = getchar();
	while(c < '0' || c > '9') {
		if(c == '-')
			op = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9') {
		N = (N << 1) + (N << 3) + (c ^ 48);
		c = getchar();
	}
	N *= op;
}
const int MAXN = 1e6 + 5;
struct Node {
	int to, dist;
	Node() {}
	Node(int T, int D) {
		to = T;
		dist = D;
	}
};
vector<Node> v[MAXN];
deque<int> q;
int dis[MAXN];
bool inque[MAXN];
int n, m, s;
void Write() {
	for(int i = 1; i <= n; i++)
		if(dis[i] != INF)
			printf("%d ", dis[i]);
		else
			printf("2147483647 ");
}
void SPFA() {
	int iqn = 1, fis = 0;
	memset(dis, 0x3f, sizeof(dis));
	dis[s] = 0;
	memset(inque, 0, sizeof(inque));
	inque[s] = true;
	q.push_back(s);
	while(!q.empty()) {
		int now = q.front(); q.pop_front();
		inque[now] = false;
		fis -= dis[now];
		iqn--;
		int SIZ= v[now].size();
		for(int i = 0; i < SIZ; i++) {
			int next = v[now][i].to;
			if(dis[next] > dis[now] + v[now][i].dist) {
				dis[next] = dis[now] + v[now][i].dist;
				if(!inque[next]) {
					inque[next] = true;
					if(q.empty() || dis[next] > dis[q.front()] || dis[next] * iqn <= fis)
						q.push_back(next);
					else
						q.push_front(next);
					fis += dis[next] + v[now][i].dist;
					iqn++;
				}
			}
		}
	}
}
void Read() {
	int A, B, C;
	Quick_Read(n);
	Quick_Read(m);
	Quick_Read(s);
	for(int i = 1; i <= m; i++) {
		Quick_Read(A);
		Quick_Read(B);
		Quick_Read(C);
		v[A].push_back(Node(B, C));
	}
}
int main() {
	Read();
	SPFA();
	Write();
	return 0;
}

但上述优化也有缺陷,并不适用与所有图。

\(LLL\) 优化常见卡掉的方法很简单,向 \(1\) 连接一条权值巨大的边,这样 \(LLL\) 也无能为力,之前做的松弛等于白费。

\(SLF\) 使用链套菊花,可以轻松卡掉。

若全部边权正负性相同,还是使用 \(Dijkstra\) 算法,其稳定性是 \(SPFA\) 不具有的。

posted @ 2020-12-09 20:10  Last_Breath  阅读(422)  评论(0编辑  收藏  举报