Bellman_ford算法,SPFA
来源:互联网 发布:如何评价张作霖 知乎 编辑:程序博客网 时间:2024/06/05 01:51
Bellman_ford算法解决带负权边的带权有向图单源最短路问题。当图中不存在带负权的环时,可以求出单源最短路;当图中存在负权环时,可以判断出来;
时间复杂度:
邻接矩阵存图时 V^3;
邻接表存图时 V*E
算法思想:(设源点为s)
构造一个最短路径长度数组序列dist(1)[u],dist(2)[u],dist(3)[u],,,,,,,,dist(n-1)[u];其中:dist(k)[u]表示从源点s只经过k条边(不构成负权回路)的最短路径长度,则有dist(1)[u] = 边(s,u)权值,最终结果为dist(n-1)[u];
求dist(k)[u]:
(1)、当k = 1 时,dist(1)[u] = 边(s,u)权值;
(2)、假设已经求出了dist(k-1)[u](u = 0,1,,,,n-1);则用每一个和u相连的节点v(对于每条边(v,u)),计算出min(dist(k-1)[v] + 边(v,u)的权值为w;则dist(k) = min(dist(k-1)[u],w);
负权回路判断:求出dist(n-1)[u](u = 0,1,2,,,,n-1之后),在对每条边(x,y)判断一下:dist[x] + 边(x,y)的值 <dist[y];如果等式成立则有负权回路(n各节点的图中,某条路径上有n条边,则一定有回路);
poj 3259 Bellman _ford 模板题(邻接表存图);
#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<climits>#include<cctype> #include<iostream>#include<algorithm>#include<queue>#include<vector>#include<map>#include<set>#include<string>#include<stack>#define ll long long#define MAX 1000#define INF 1000000000#define eps 1e-8using namespace std;struct Edge{int from, to, dist;};vector<int>G[MAX];vector<Edge>edges;int n;void init(){for (int i=0; i<=n; i++) G[i].clear();edges.clear();}void addEdge(int from, int to, int dist){edges.push_back((Edge){from,to,dist});int k = edges.size();G[from].push_back(k-1);}bool Bellman_ford(int s){int d[MAX];for (int i=0; i<n; i++) d[i] = (i == s ? 0 : INF);for (int i=1; i<n; i++){for (int j = 0; j<edges.size(); j++){Edge e = edges[j];if (d[e.from] < INF){d[e.to] = min(d[e.to] , d[e.from] + e.dist);}}}for (int i=0; i<edges.size(); i++){Edge e = edges[i];if (d[e.to] > d[e.from] + e.dist) return true;}return false;}int main(){int T,m,w;scanf("%d",&T);while (T--){init();scanf("%d%d%d",&n,&m,&w);int x,y,z;for (int i=0; i<m; i++){scanf("%d%d%d",&x,&y,&z);addEdge(x-1,y-1,z);addEdge(y-1,x-1,z);}for (int i=0; i<w; i++){scanf("%d%d%d",&x,&y,&z);addEdge(x-1,y-1,-z);}if (Bellman_ford(0)) printf("YES\n");else printf("NO\n");}return 0;}
SPFA:
用于快速求解单源最短路和判断图中是否有负权回路,是Bellma_ford的改进,采用了队列优化;期望的时间复杂度为O(E);
算法思想:(源点为s; d[i]记录节点i 到源点的当前最短距离);
(1)初始化d[s] = (s == 0 ? 0 : INF),维护一个队列,里面存放所有需要进行迭代的点,初始化只有一个点s;并用一个数组表示节点是否在队列中,一个数组记录节点的入队次数。
(2)每次迭代时取队首元素u;枚举所有与之相连的边v;(u->v)设其权值为w;判断d[u] + w < d[v];如果成立:更新d[v];判断v是否在队列中,若不在,则入队并判断节点v入队次数,如果入队次数大于等于n则存在负权回路;
poj3259 SPFA模板题目(判断有无负权回路);
#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<climits>#include<cctype>#include<iostream>#include<algorithm>#include<queue>#include<vector>#include<set>#include<stack>#include<string>#include<map>#define ll long long#define MAX 1000#define INF 1000000000#define eps 1e-8using namespace std;struct Edge{int from,to,dist;};vector<int>G[MAX];vector<Edge>edges;int n;void init(){for (int i=0; i<=n; i++) G[i].clear();edges.clear();}void addEdge(int from, int to,int dist){edges.push_back((Edge){from,to,dist});int k = edges.size();G[from].push_back(k-1);}bool Bellman_ford(int s){bool inq[MAX]; //记录节点是否在队列中int cnt[MAX]; //记录节点入队的次数queue<int>q;int d[MAX];memset(inq,0,sizeof(inq));memset(cnt,0,sizeof(cnt));for (int i=0; i<n; i++) d[i] = (i == s ? 0 : INF);for (int i=0; i<n; i++){q.push(i); //首先让所有点都入队,防止图不连通。 求连通图的最短路时,只需先将源点入队就行 inq[s] = true; //d[i] = 0; 只是判断有无负权回路可以直接让d[i] = 0;并让所有的节点入队 }while (!q.empty()){int u = q.front();q.pop();inq[u] = false;for (int i = 0; i<G[u].size(); i++){Edge e = edges[G[u][i]];if (d[e.to] > d[u] + e.dist){d[e.to] = d[u] + e.dist;if (!inq[e.to]){ //思考?什么时候才需要入队 q.push(e.to);inq[e.to] = true;if (++cnt[e.to] >= n) return true; //当某个节点入队超过n次说明图中存在负权回路 } }}}return false;}int main(){int T,m,w;scanf("%d",&T);while (T--){init();scanf("%d%d%d",&n,&m,&w);int x,y,z;for (int i=0; i<m; i++){scanf("%d%d%d",&x,&y,&z);addEdge(x-1,y-1,z);addEdge(y-1,x-1,z);}for (int i=0; i<w; i++){scanf("%d%d%d",&x,&y,&z);addEdge(x-1,y-1,-z);}if (Bellman_ford(0)) printf("YES\n");else printf("NO\n");}return 0;}
- Bellman_Ford算法->SPFA算法
- Spfa算法+bellman_ford算法
- Bellman_ford算法,SPFA
- SPFA算法 Bellman_ford优化
- Dijkstra、Bellman_Ford、SPFA、Floyd算法复杂度比较
- Dijkstra、Bellman_Ford、SPFA、Floyd算法复杂度比较
- Dijkstra、Bellman_Ford、SPFA、Floyd算法复杂度比较
- Dijkstra、Bellman_Ford、SPFA、Floyd算法复杂度比较
- 最短路 dijkstra算法 poj2387 bellman_ford spfa
- Dijkstra、Bellman_Ford、SPFA、Floyd算法复杂度比较
- 单源最短路径:Dijkstra 算法 Bellman_Ford 算法 SPFA 算法
- poj 3259 最短路判负环 spfa算法和Bellman_ford算法
- poj3259( spfa 和 bellman_ford)
- Bellman_ford算法
- Bellman_ford算法
- Bellman_ford算法
- Bellman_Ford 算法
- Bellman_Ford算法
- 高精度进制转换
- android 自定义 4.0的spinner 自定义spinner的字体和颜色
- VMWARE 2013 校园招聘要求
- ZOJ 3790 Consecutive Blocks 排序+扫描
- hdu 4901 The Romantic Hero 计数dp,位计算
- Bellman_ford算法,SPFA
- ubuntu下 简单配置samba,实现 共享夹
- 排列组合的算法
- POJ 2342 树形DP入门题
- mac下SVN上传.a静态库文件
- Shader之CubeMap 和基于法线的CubeMap
- vc++中实现进度条
- IntelliJ IDEA 使用SVN时报错:Subversion: (Accessing URL: XXX) SSLProtocolException: alert code: 112 alert
- Java学习之道:Java操作Excel之导出下载