「学习笔记」SPFA 算法的优化

与其说是 SPFA 算法的优化,倒不如说是 Bellman-Ford 算法的优化。

栈优化#

将原本的 bfs 改为 dfs,在寻找负环时可能有着更高效的效率,但是最坏复杂度为指数级别。

void dfs_spfa(int u) {
	if (fg)    return;
	vis[u] = true;
	for(pil it : son[u]) {
		int v = it.first;
		ll w = it.second;
		if (dis[v] > dis[u] + w) {
			dis[v] = dis[u] + w;
			if (vis[v] == true) {//如果这个点被访问过,就说明这是负环 
				fg = true;//打标记 
				return;
			}
			else    dfs_spfa(v);
		}
	}
	vis[u] = false;
}

SLF 优化#

queue 换成 deque,判断与队首元素的 dis 的大小,小的就放队首,大的就放队尾。

void spfa(int s) {
	for(int i = 1; i <= n; ++ i) {
		dis[i] = inf;
	}
	dis[s] = 0;
	q.push_back(s);
	f[s] = 1;
	while (!q.empty()) {
		int u = q.front();
		q.pop_front();
		f[u] = 0;
		for (pii it : son[u]) {
			int v = it.first;
			int w = it.second;
			if (dis[v] > dis[u] + w) {
				dis[v] = dis[u] + w;
				if (! f[v]) {
					if (! q.empty() && dis[v] < dis[q.front()]) {
						q.push_front(v);
					}
					else    q.push_back(v);
					f[v] = 1;
				}
			}
		}
	}
}

D´Esopo-Pape 优化#

queue 换成 deque,判断一个点是否入过队列,没入过就放到队尾,如果就放到队首。

void spfa(int s) {
	for(int i = 1; i <= n; ++ i) {
		dis[i] = inf;
	}
	dis[s] = 0;
	q.push_back(s);
	f[s] = 1;
	vis[s] = 1; // 是否入过队
	while (!q.empty()) {
		int u = q.front();
		q.pop_front();
		f[u] = 0;
		for (pii it : son[u]) {
			int v = it.first;
			int w = it.second;
			if (dis[v] > dis[u] + w) {
				dis[v] = dis[u] + w;
				if (! f[v]) {
					if (vis[v]) {
						q.push_front(v);
					}
					else {
						q.push_back(v);
						vis[v] = 1;
					}
					f[v] = 1;
				}
			}
		}
	}
}

LLL 优化#

queue 换成 deque,每次将入队结点距离和队内距离平均值比较,如果更大则插入至队尾,否则插入队首。

void spfa() {
	ll sum = 0;
	for (int i = 1; i <= n; ++ i) {
		dis[i] = inf;
	}
	dis[s] = 0;
	q.push_back(s);
	g[s] = 1;
	sum += dis[s];
	while (!q.empty()) {
		int u = q.front();
		q.pop_front();
		vis[u] = false;
		sum -= dis[s];
		for (pli it : son[u]) {
			if (dis[it.second] > dis[u] + it.first) {
				dis[it.second] = dis[u] + it.first;
				if (! vis[it.second]) {
					if (q.empty() || dis[it.second] > sum / ((int)q.size())) {
						q.push_back(it.second);
					}
					else {
						q.push_front(it.second);
						g[it.second] = 1;
					}
					vis[it.second] = true;
				}
			}
		}
	}
}

SLF 带容错优化#

queue 换成 deque,判断与队首元素的 dis 的大小,设定一个值 W,如果比队首元素大超过 W 则放队尾。

W 一般设为所有边权的和的开方,即 sum

mcfx 优化#

在第 [L,R] 次访问一个结点时,将其放入队首,否则放入队尾。通常取 L=2,R=|V|

SLF + swap 优化#

每当队列改变时,如果队首距离大于队尾,则交换首尾。

作者:yifan0305

出处:https://www.cnblogs.com/yifan0305/p/17366120.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

转载时还请标明出处哟!

posted @   yi_fan0305  阅读(196)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示