算法基础 - 单源点最短路径SPFA
2016-05-08 02:41
281 查看
SPFA是非常简单的最短路径算法,思想就是从起点开始,进行宽度优先搜索,不断松弛S点到其他相邻点的距离。如果松弛了点B,则把点B放到队列里。假如点B已经在队列里了,就不要放了,判断在不在队列可以用个数组来表示。
引用一段hihocoder上的解释:
构造一个队列,最开始队列里只有(S, 0)——表示当前处于点S,从点S到达该点的距离为0,然后每次从队首取出一个节点(i, L)——表示当前处于点i,从点S到达该点的距离为L,接下来遍历所有从这个节点出发的边(i, j, l)——表示i和j之间有一条长度为l的边,将(j, L+l)加入到队尾,最后看所有遍历的(T, X)节点中X的最小值就是答案咯~”小Ho对于搜索已经是熟稔于心,张口便道。
SPFA算法呢,其实某种意义上就是宽度优先搜索的优化——如果你在尝试将
“那我该怎么知道队列中是不是存在一个
维护一个
“所以说这本质上就是宽度优先搜索的剪枝咯?”小Ho问道。
小Hi笑道:“怎么可能!SPFA算法其实是BELLMAN-FORD算法的一种优化版本,只不过在成型之后可以被理解成为宽度优先搜索的!这个问题,我们会在之后好好讲一讲的!
代码如下:
大致如上
引用一段hihocoder上的解释:
构造一个队列,最开始队列里只有(S, 0)——表示当前处于点S,从点S到达该点的距离为0,然后每次从队首取出一个节点(i, L)——表示当前处于点i,从点S到达该点的距离为L,接下来遍历所有从这个节点出发的边(i, j, l)——表示i和j之间有一条长度为l的边,将(j, L+l)加入到队尾,最后看所有遍历的(T, X)节点中X的最小值就是答案咯~”小Ho对于搜索已经是熟稔于心,张口便道。
SPFA算法呢,其实某种意义上就是宽度优先搜索的优化——如果你在尝试将
(p, q)加入到队尾的时候,发现队列中已经存在一个
(p, q')了,那么你就可以比较q和q’:如果
q>=q',那么
(p, q)这个节点实际上是没有继续搜索下去的必要的——算是一种最优化剪枝吧。而如果
q < q',那么
(p, q')也是没有必要继续搜索下去的——但是它已经存在于队列里了怎么办呢?很简单,将队列中的
(p, q')改成
(p, q)就可以了!”
“那我该怎么知道队列中是不是存在一个
(p, q')呢?”
维护一个
position[1..N]的数组就可以了,如果不在队列里就是-1,否则就是所在的位置!”
“所以说这本质上就是宽度优先搜索的剪枝咯?”小Ho问道。
小Hi笑道:“怎么可能!SPFA算法其实是BELLMAN-FORD算法的一种优化版本,只不过在成型之后可以被理解成为宽度优先搜索的!这个问题,我们会在之后好好讲一讲的!
代码如下:
#include <iostream> #include <cstring> #include <string> #include <queue> using namespace std; struct Node{ int val; int len; Node * next; Node():val(-1),len(-1), next(NULL){} Node(int x, int le): val(x), len(le), next(NULL){} }; long long SPFA(Node node[], int M, int S, int T){ queue<int> st; st.push(S); int flag[M+5]; long long dist[M+5]; for(int i = 0; i < M+5; i++){ flag[i] = 0; dist[i] = -1; } dist[S] = 0; flag[S] = 1; while(!st.empty()){ int cur = st.front(); st.pop(); flag[cur] = 0; Node * temp = node[cur].next; while(temp != NULL){ if(dist[temp->val] == -1 || dist[temp->val] > (dist[cur]+temp->len)){ dist[temp->val] = dist[cur]+temp->len; if(flag[temp->val] == 0){ st.push(temp->val); flag[temp->val] = 1; } } temp = temp->next; } } return dist[T]; } int main(){ int M,N,S,T; // M 顶点个数, N 边个数, S起点, T 终点 while(cin>>M>>N>>S>>T){ Node node[M+5]; int st, en, le; for(int i = 0; i < N;i++){ cin>>st>>en>>le; //st边起点 en边终点 le边长度 Node * temp = new Node(en,le); temp->next = node[st].next; node[st].next = temp; /*如果是无向图加上这三条语句 temp = new Node(st,le); temp->next = node[en].next; node[en].next = temp; */ } cout<<SPFA(node, M, S, T)<<endl; } }
大致如上
相关文章推荐
- CSU1307 并查集+SPFA
- 最短路径 -- spfa
- 单源最短路深度分析
- hdoj 1874 畅通工程 vector邻接表测试
- USACO/butter 3.2.6
- 【POJ1860】Currency Exchange
- hdu 1596 find the safest road(spfa算法)
- MZ Training 2014 #8 F题
- MZ Training 2014 #4 B题
- [网络流24题 #18]分配问题
- [网络流24题 #18]分配问题
- 收益最大
- acm-hdu2544解题报告
- hdu2112 spfa
- POJ 3037 Skiing SPFA
- POJ 3255 Roadblocks 次短路 SPFA
- poj 1511 Invitation Cards
- poj 1724 ROADS 邻接表+优先队列+spfa()
- hdu 1224 Free DIY Tour
- hdu2544最短路——spfa