最短路(2)--bellman-ford和SPFA
来源:互联网 发布:振动分析软件 航空 编辑:程序博客网 时间:2024/06/17 14:10
bellman-ford
首先,如果最短路存在,那么一定有一条不含环的最短路,因为如果是正环或零环,都可以直接去除,如果有负环,则最短路不存在,所以最短路顶多经过n-1个顶点,那么我们至多只需要进行n-1次松弛操作,每次操作中遍历所有边,如果该边的起点不是INF(已经松弛过)那么就对该边的终点松弛。这样就一定可以把最短路经过的所有点都松弛一遍,即求出了最短路(因为只要可以松弛,就一定有更短的方案)。
//bellmanford#include<cstdio>#include<cstdlib>#include<iostream>#include<algorithm>using namespace std;const int MAXN = 1000 + 10;const int INF = 0x3f3f3f3f;int u[MAXN], v[MAXN], w[MAXN];int d[MAXN];int n, m;int main(){ freopen("sp.in", "r", stdin); cin >> n >> m; for(int i = 1; i <= m; i++) { cin >> u[i] >> v[i] >> w[i]; u[i+m] = v[i], v[i+m] = u[i], w[i+m] = w[i]; } d[1] = 0; for(int i = 2; i <= n; i++) d[i] = INF; for(int k = 1; k < n; k++) for(int i = 1; i <= 2*m; i++) if(d[u[i]] < INF) d[v[i]] = min(d[v[i]], d[u[i]] + w[i]); for(int i = 1; i <= n; i++) cout << d[i] << " "; return 0;}
SPFA
思路:
- 把除起点外的所有点距离设为无限,然后让起点进入队列
- 每次取出队列的第一个点,讨论他的所有只向点进行松弛操作,如果松弛成功并且该点并不在队列中,将该点放入队列,直到队列中没有点为止
和dijkstra的比较
- dijkstra每次取出的是当前距离最小点,在后面的讨论中不可能再更新该点的值,所以每个点只用讨论一次
- SPFA每次取出的只是一个松弛过的点,很有可能再次讨论回来,所以一个点要讨论多次
- 但是因为dijkstra中每次找距离最小点需要时间复杂度,所以O(mlogn)
- 而SPFA没有这个需要,所以O(kn),k是常数,而一般不会超过2
- 而且dijkstra只能解决没有负权的问题,而SPFA可以解决,但不能解决有负环的问题,因为有负环的图没有最短路,他还可以判定负环,当一个点的进队次数超过n后,可以判定图中有负环
下面是SPFA的代码
//SPFA#include<cstdio>#include<cstdlib>#include<queue>#include<iostream>#include<algorithm>using namespace std;const int MAXN = 10000 + 10;const int INF = 0x3f3f3f3f;queue<int> q;int n, m;int d[MAXN];int vis[MAXN];struct edge{ int to, next, w;}e[MAXN]; int head[MAXN], cnt;void add(int u, int v, int w){ e[++cnt].next = head[u]; head[u] = cnt; e[cnt].to = v; e[cnt].w = w;}int main(){ freopen("sp.in", "r", stdin); cin >> n >> m; for(int i = 1; i <= m; i++) { int u, v, w; cin >> u >> v >> w; add(u, v, w); add(v, u, w); } for(int i = 2; i <= n; i++) d[i] = INF; q.push(1); vis[1] = 1; while(!q.empty()) { int u = q.front(); q.pop(); vis[u] = 0; for(int i = head[u]; i; i = e[i].next) { int v = e[i].to; if(d[v] > d[u] + e[i].w) { d[v] = d[u] + e[i].w; if(!vis[v]) {q.push(v); vis[v] = 1;} } } } for(int i = 1; i <= n; i++) cout << d[i] << " "; return 0;}
0 0
- 最短路(2)--bellman-ford和SPFA
- 最短路 SPFA (对于bellman-ford 的优化)
- POJ 3259 Wormholes (图论---最短路 Bellman-Ford || SPFA)
- HDU-#2544 最短路(Dijkstra、Floyd、Bellman-Ford、SPFA)
- 暑假-最短路(Bellman-ford、spfa)-A - Arbitrage
- 暑假-最短路(Bellman-ford、spfa)-F - Wormholes
- 最短路算法(Floyd、Dijsktra、Bellman-Ford、SPFA)
- 最短路算法(Floyd、Dijsktra、Bellman-Ford、SPFA)
- 最短路(SPFA、Dijkstra、Floyd、Bellman-Ford)
- 最短路知识点总结(Dijkstra,Floyd,SPFA,Bellman-Ford)
- C--最短路(Bellman-Ford或者SPFA)
- 最短路知识点总结(Dijkstra,Floyd,SPFA,Bellman-Ford)
- 最短路算法 Dijkstra Bellman-Ford SPFA
- Bellman-Ford(最短路)
- 最短路 bellman-ford
- 最短路~bellman-ford
- 最短路-Bellman-Ford
- HDU1874(最短路问题:Dijskra+Floyd+Bellman-Ford+SPFA)
- Android 通知(Notification)的使用
- utf-8和GBk的区别
- Java基础--控制语句
- 51单片机与protues仿真联合基础教程(一)--创建工程
- 队列学习
- 最短路(2)--bellman-ford和SPFA
- JAVA 使用FileReader/FileWriter复制文件
- java实现将汉语转换为拼音
- HDU 1016 Prime Ring Problem
- 从Hibernate4到Hibernate5的建表
- Java多线程
- iOS中图形图像处理第一部分:位图图像原图修改
- 选择排序
- 在变量作用域方面,函数声明和函数表达式有什么区别?