图的单源最短路径SPFA算法
来源:互联网 发布:mac怎么移动窗口 编辑:程序博客网 时间:2024/05/27 01:48
算法大致流程
一个队列来进行维护。初始时将源加入队列。每次从队列中取出一个元素,并对所有与他相邻的点进行松弛,若某个相邻的点松弛成功,则将其入队。直到队列为空时算法结束。
设Dist代表S到I点的当前最短距离,Fa代表S到I的当前最短路径中I点之前的一个点的编号。
1.开始时Dist全部为+∞,只有Dist[S]=0,Fa全部为0。维护一个队列,里面存放所有需要进行迭代的点。初始时队列中只有一个点S。用一个布尔数组记录每个点是否处在队列中。
2.每次迭代,取出队头的点v,依次枚举从v出发的边v->u,设边的长度为len,判断Dist[v]+len是否小于 Dist[u],若小于则改进Dist[u],将Fa[u]记为v,并且由于S到u的最短距离变小了,有可能u可以改进其它的点,所以若u不在队列中,就将它放入队尾。
3.这样一直迭代下去直到队列变空,每次的优化将会有某个点v的最短路径估计值Dist[v]变小。所以算法的执行会使d越来越小。由于我们假定图中不存在负权回路,所以每个结点都有最短路径值。因此,算法不会无限执行下去,随着Dist值的逐渐变小,直到到达最短路径值时,算法结束,这时的最短路径估计值就是对应结点的最短路径值若一个点入队次数超过n,则有负权环。
SPFA 在形式上和宽度优先搜索非常类似,不同的是宽度优先搜索中一个点出了队列就不可能重新进入队列,但是SPFA中一个点可能在出队列之后再次被放入队列,也就是一个点改进过其它的点之后,过了一段时间可能本身被改进,于是再次用来改进其它的点,这样反复迭代下去。
以hdu 1874为例
#include <iostream>#include <queue>using namespace std;const int INF=100000000;const int MAX=1005;struct node //邻接表存储{ int to,w; int next;}e[MAX];int head[MAX],path[MAX],dist[MAX];int Count[MAX]; //记录每个点入队次数int n;bool vis[MAX];bool SPFA(int v0){ queue<int>q; for (int i=0; i<n; i++) //初始化 { dist[i]=INF; path[i]=v0; vis[i]=false; Count[i]=0; } dist[v0]=0; vis[v0]=true; //标记 q.push(v0); Count[v0]++; while (!q.empty()) { int u=q.front(); q.pop(); if(Count[u]>n) { return false; } vis[u]=false; for (int i=head[u]; i!=-1; i=e[i].next) //访问邻接点 { int v=e[i].to; if(dist[v]>dist[u]+e[i].w) { dist[v]=dist[u]+e[i].w; //更新 path[v]=u; if(!vis[v]) //如果不在队列则再次入队。 { q.push(v); vis[v]=true; //标记 } } } } return true; }void ShowPath(int v0,int v) //显示路径{ int num[MAX]; int pos=0; num[pos++]=v; int k=path[v]; while (k!=v0) { num[pos++]=k; k=path[k]; } num[pos++]=v0; for (int i=pos-1; i>=0; i--) { printf("%d ",num[i]); } printf("\n"); }int main(){ int m,u,v,w,cnt; while (scanf("%d%d",&n,&m)!=EOF) { cnt=0; memset(head, -1, sizeof(head)); while (m--) { scanf("%d%d%d",&u,&v,&w); //添加边 e[cnt].to=v; e[cnt].w=w; e[cnt].next=head[u]; head[u]=cnt++; //这里是无向图 e[cnt].to=u; e[cnt].w=w; e[cnt].next=head[v]; head[v]=cnt++; } int s,t; scanf("%d%d",&s,&t); if(!SPFA(s)||dist[t]==INF) { printf("-1\n"); } else { printf("%d\n",dist[t]); for (int i=1; i<n; i++) { printf("路径长度(0--%d):%d path:",i,dist[i]); ShowPath(0, i); } } } return 0;}
dfs的spfa
bool spfa(int u){ vis[u]=true; for (int i=head[u]; i!=-1; i=e[i].next) { int v=e[i].to; if(dist[u]+e[i].w<dist[v]) { dist[v]=dist[u]+e[i].w; path[v]=u; if(!vis[v]) { if(spfa(v)) { return 1; } } else { return 1; } } } vis[u]=false; return 0;}
0 0
- 图的单源最短路径SPFA算法
- 单源最短路径的SPFA算法
- 单源最短路径-spfa算法
- Spfa单源最短路径算法
- 单源最短路径:SPFA算法
- 单源最短路径SPFA算法-邻接矩阵
- SPFA:改进的BellmanFord求单源最短路径算法
- 最短路径的SPFA算法
- 单源最短路径之SPFA算法实现
- SPFA算法——单源最短路径
- 单源最短路径 ——SPFA算法
- SPFA算法 蓝桥杯 单源最短路径(含负权)
- 邻接表实现 单源最短路径SPFA算法
- 单源最短路径--Bellman-Ford算法及SPFA
- 图算法补充(SPFA,最长路径)
- SPFA算法求最短路径
- SPFA算法求单源最短路径
- 求含有负权边的图的单源最短路径——Bellman Ford算法与SPFA算法综合分析
- Unix环境高级编程学习笔记1—a.out的实现
- servlet线程安全性问题
- Android 编程之天气预报小实例源码演示及效果展示--1
- HDU 5017 模拟退火
- netbeans 出现Enter password for default keyring to unlock 问题的解决方案
- 图的单源最短路径SPFA算法
- 解决Odoo访问fonts.googleapis.com导致速度慢的问题
- 最简单易用的verilog学习练习工具silos初次使用。
- 故障排除:"log file sync"等待 (文档 ID 1626301.1)
- linux 进程的控制
- 漫谈机器学习经典算法—特征提取与特征选择
- 阿里云 django的一次web维护记录
- 利用单链表实现多相式的相加
- Cocos2d-JS 使用定时器取消往图片、骨骼动画添加的shader