SPFA算法(最短路径)
2016-04-06 22:18
316 查看
Bellman-ford算法的基础上加上一个队列优化,减少了冗余的松弛操作,是一种高效的最短路算法。
设立一个先进先出的队列用来保存待优化的结点,优化时每次取出队首结点u,并且用u点当前的最短路径估计值对离开u点所指向的结点v进行松弛操作,如果v点的最短路径估计值有所调整,且v点不在当前的队列中,就将v点放入队尾。这样不断从队列中取出结点来进行松弛操作,直至队列空为止。
如果某个点进入队列的次数超过N次则存在负环(SPFA无法处理带负环的图)。
设立一个先进先出的队列用来保存待优化的结点,优化时每次取出队首结点u,并且用u点当前的最短路径估计值对离开u点所指向的结点v进行松弛操作,如果v点的最短路径估计值有所调整,且v点不在当前的队列中,就将v点放入队尾。这样不断从队列中取出结点来进行松弛操作,直至队列空为止。
如果某个点进入队列的次数超过N次则存在负环(SPFA无法处理带负环的图)。
#include<iostream> #include<vector> #include<deque> using namespace std; struct Edge { int to,length; }; bool spfa(const int &beg,//出发点 const vector<vector<Edge> > &adjlist,//邻接表,通过传引用避免拷贝 vector<int> &dist,//出发点到各点的最短路径长度 vector<int> &path)//路径上到达该点的前一个点 //出现负权回路返回1! { const int &INF=0x7FFFFFFF,&NODE=adjlist.size(); dist.assign(NODE,INF);//初始化距离为无穷大 path.assign(NODE,-1); deque<int> que(1,beg); vector<bool> flag(NODE,0);//标志数组,判断是否在队列中 vector<int> cnt(NODE,0);//记录各点入队次数,用于判断负权回路 dist[beg]=0;//出发点到自身路径长度为0 ++cnt[beg];//开始计数 flag[beg]=1;//入队 while(!que.empty()) { const int now=que.front(); que.pop_front(); flag[now]=0;//将该点拿出队列 for(int i=0; i!=adjlist[now].size(); ++i)//遍历所有与当前点有路径的点 { const int &next=adjlist[now][i].to; if(dist[now]<INF&&//若距离已知,且优于当前值 dist[next]>dist[now]+adjlist[now][i].length) { dist[next]=dist[now]+adjlist[now][i].length; path[next]=now;//记录路径 if(!flag[next])//若未在处理队列中 { if(++cnt[next]==NODE)return 1;//计数后出现负权回路 if(que.empty()|| dist[next]<dist[que.front()])//优先级高于队首 que.push_front(next);//放在队首 else que.push_back(next);//否则放在队尾 flag[next]=1;//入队 } } } } return 0; } int main() { int n_num,e_num,beg;//含义见下 cout<<"输入点数、边数、出发点:"; cin>>n_num>>e_num>>beg; vector<vector<Edge> > adjlist(n_num,vector<Edge>());//默认初始化邻接表 for(int i=0,p; i!=e_num; ++i) { Edge tmp; cout<<"输入第"<<i+1<<"条边的起点、终点、长度:"; cin>>p>>tmp.to>>tmp.length; adjlist[p].push_back(tmp); } vector<int> dist,path;//用于接收最短路径长度及路径各点 if(spfa(beg,adjlist,dist,path))cout<<"图中存在负权回路\n"; else for(int i=0; i!=n_num; ++i) { cout<<beg<<"到"<<i<<"的最短距离为"<<dist[i]<<",反向打印路径:"; for(int w=i; path[w]>=0; w=path[w]) cout<<w<<"<-"; cout<<beg<<'\n'; } }
相关文章推荐
- codeforce 332B Maximum Absurdity
- 【USACO题库】5.3.4 Big Barn巨大的牛棚
- Linux内核分析——第七周学习笔记20135308
- 30个php操作redis常用方法代码例子
- 设置流程变量
- cf#301-C. Ice Cave-BFS
- 三角形2
- 深度剖析智能指针
- 把字符串中的空格替换成“00”
- POJ1062 昂贵的聘礼
- JavaScript基础教程01编辑器的选择和两种链接方法
- 1007 DNA Sorting(字符串+逆序数)
- 训练集(train set) 验证集(validation set) 测试集(test set)
- 中国历史上成功的两人合作
- 菜单
- HDU 3535 分组混合背包
- C++继承之后的访问方式
- ava对数组元素排序的三种方式
- Mac 使用SSH远程登录
- 使用SharedPreferences保存用户名和密码