SPFA算法
2018-03-12 22:18
141 查看
SPFA算法
用途用于解决单源最短路径问题,可以处理含有负边权边的图(若存在源点可达负环则无解)。
算法描述
SPFA算法是在Bellman-Ford算法基础上改进得来的 (关于BF算法可参考 《Bellman-Ford算法》)。BF算法时间复杂度较高,原因在于每一次循环都需要遍历图中所有边,其中包含了大量的重复遍历,这就会使算法效率大大降低。SPFA算法依据的原理是:只有当某个结点到源点的最短距离d[i]改变后,由结点i出发可达的结点j与源点的最短距离d[j]才可能会被改变。由此可以对BF算法进行优化得到期望时间复杂度为O(kE)O(kE) (k为常数,E为边数)的SPFA算法,其主要步骤如下:
建立队列q,将源点入队;
队首结点u出队,遍历u的所有出边 u->v 进行松弛操作,如果 d[u] + length[u->v] < d[v], 则用较小值更新d[v],若此时v不在队列中,则将其入队;
当队列非空时,重复步骤2,同时每次操作要判断是否有某个结点的入队次数大于 n - 1,若有则说明图中存在从源点可达的负环,结束算法并返回false;
所有最短距离优化完毕,结束算法并返回true。
代码实现
const int maxn = 1000; const int INF = 1000000000; struct node { int v, l; }; vector<node> adjL[maxn]; // 邻接表 int n; // 结点个数 int d[maxn]; // 结点i到源点的最短距离 int num[maxn]; // 结点i的入队次数 bool inq[maxn]; // 结点i是否已入队 bool SPFA(int s) { for (int i = 0; i < n; i++) // 初始化 { num[i] = 0; d[i] = INF; inq[i] = false; } d[s] = 0; // 源点到自身距离为0 queue<int> q; q.push(s); // 源点入队 num[s]++; inq[s] = true; while (!q.empty()) // 队非空一直循环 { int u = q.front(); // 队首结点出队 q.pop(); inq[u] = false; for (int i = 0; i < adjL[u].size(); i++) // 遍历所有出边 { int v = adjL[u][i].v; int l = adjL[u][i].l; if (d[u] + l < d[v]) // 松弛 { d[v] = d[u] + l; if (!inq[v]) { q.push(v); inq[v] = true; num[v]++; if (num[v] > n - 1) // 入队次数超过 n - 1,说明存在源点可达负环,返回false return false; } } } } return true; }
相关文章推荐
- SPFA算法
- 最短路径之SPFA算法
- Spfa算法 (模板源代码)
- 最短路——SPFA算法模板
- 最短路径 之 SPFA算法
- 杭电2544-最短路 -spfa算法求解最短路
- 邻接表实现 单源最短路径SPFA算法 poj1511
- SPFA算法详解
- SPFA算法
- 最短路算法 :Bellman-ford算法 & Dijkstra算法 & floyd算法 & SPFA算法 详解
- SPFA算法及其应用和优化
- SPFA算法-单源最短路径算法
- SPFA算法
- 总结分析一下三种求解最短路问题的算法,dijkstra算法,spfa算法,floyd算法。
- hihocoder #1093 : 最短路径·三:SPFA算法
- 最短路径:我的理解--SPFA算法
- Bellman flod SPFA算法再解
- SPFA算法模板例题[POJ1062]-昂贵的聘礼
- SPFA算法
- POJ 1511 Invitation Cards(最短路spfa算法)