知识概览
- SPFA算法是Bellman_Ford算法的优化。时间复杂度一般是O(m),最坏时间复杂度是O(nm)(遇到网格图、菊花图),其中n是点数,m是边数。
- SPFA算法其实是单源最短路限制最小的算法,只要图中没有负环,就一定可以用SPFA算法。
- SPFA算法可以解决有负权边的问题,也可以解决没有负权边的问题,而且效率还比Dijkstra算法快,可以说是时间复杂度最高的算法,非常常用。
例题展示
题目链接
SPFA求最短路
活动 - AcWing 系统讲解常用算法与数据结构,给出相应代码模板,并会布置、讲解相应的基础算法题目。https://www.acwing.com/problem/content/853/
代码
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>using namespace std;const int N = 100010;int n, m;
int h[N], w[N], e[N], ne[N], idx;
int dist[N];
bool st[N];void add(int a, int b, int c)
{e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}int spfa()
{memset(dist, 0x3f, sizeof dist);dist[1] = 0;queue<int> q;q.push(1);st[1] = true;while (q.size()){int t = q.front();q.pop();st[t] = false;for (int i = h[t]; i != -1; i = ne[i]){int j = e[i];if (dist[j] > dist[t] + w[i]){dist[j] = dist[t] + w[i];if (!st[j]){q.push(j);st[j] = true;}}}}return dist[n];
}int main()
{scanf("%d%d", &n, &m);memset(h, -1, sizeof h);while (m--){int a, b, c;scanf("%d%d%d", &a, &b, &c);add(a, b, c);}int t = spfa();if (t == 0x3f3f3f3f) puts("impossible");else printf("%d\n", t);return 0;
}
题目链接
SPFA判断负环
活动 - AcWing 系统讲解常用算法与数据结构,给出相应代码模板,并会布置、讲解相应的基础算法题目。https://www.acwing.com/problem/content/854/
代码
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>using namespace std;const int N = 100010;int n, m;
int h[N], w[N], e[N], ne[N], idx;
int dist[N], cnt[N];
bool st[N];void add(int a, int b, int c)
{e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}bool spfa()
{queue<int> q;for (int i = 1; i <= n; i++){st[i] = true;q.push(i);}while (q.size()){int t = q.front();q.pop();st[t] = false;for (int i = h[t]; i != -1; i = ne[i]){int j = e[i];if (dist[j] > dist[t] + w[i]){dist[j] = dist[t] + w[i];cnt[j] = cnt[t] + 1;if (cnt[j] >= n) return true;if (!st[j]){q.push(j);st[j] = true;}}}}return false;
}int main()
{scanf("%d%d", &n, &m);memset(h, -1, sizeof h);while (m--){int a, b, c;scanf("%d%d%d", &a, &b, &c);add(a, b, c);}if (spfa()) puts("Yes");else puts("No");return 0;
}
参考资料
- AcWing算法基础课