zoukankan      html  css  js  c++  java
  • [算法] 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) 不具有的。

  • 相关阅读:
    搭建strom 的开发环境
    maven 的plugin 的使用
    Maven 的dependency 的 classifier的作用
    Maven中的dependency的scope作用域详解
    Supervisor-进程监控自动重启
    websocket 实战
    vue 监听路由变化
    vux-uploader 图片上传组件
    vue 定义全局函数
    判断对象属性的值是否空,如为空,删除该属性
  • 原文地址:https://www.cnblogs.com/C202202chenkelin/p/14110665.html
Copyright © 2011-2022 走看看