Bellman_ford队列优化算法(SPFA):
Bellman_ford的队列优化算法,又叫SPFA算法,两者指的是同一个算法。在初始的Bellman_ford算法中,每次松弛都将所有的边松弛了一次(也就是每轮松弛的时候每条边都会被处理一次)。但其中不全是有效的松弛,因为有的节点并没有被计算过,只有针对计算过的节点进行的松弛才是有效的松弛。比如说,如果一个边的起点甚至还没有被计算过,即到达该起点的最短路径是INT_MAX,并没有被更新过,对这样起点的边进行处理是没有必要的。所以,实际上我们只需要对上一次松弛的时候更新过的节点进行松弛就好了(因为没有更新的节点说明已经找到了到达他的最短距离)。使用队列实现优化,将当前访问的节点加入队列,取出队头元素,对队头元素所代表的节点作为出发点所连接的边进行松弛。
卡码网:94.城市间货物运输 I
思路:利用队列对上一次更新过的节点进行松弛。关于list容器,是一个双向链表。
代码:
#include<iostream>
#include<vector>
#include<list>
#include<climits>
using namespace std;
#include<queue>
struct Edge{//邻接表
int to;//终点
int val;//权值
Edge(int t, int w): to(t),val(w){}//构造函数和初始化
};
int main(){
int n, m, p1, p2, val;
cin >> n >> m;//点数和边数
//邻接表里存储某个点 相连的边 以及这个边的终点以及权值
vector<list<Edge>> grid(n+1);
//记录队列中是否已经存在这个点
vector<bool> isInQueue(n+1);
for(int i=0; i<m; i++){
cin >> p1 >> p2 >> val;
//往每个节点的链表里面存放边
grid[p1].push_back(Edge{p2, val});
}
vector<int> minDist(n+1,INT_MAX);
minDist[1] = 0;
int start = 1;
int end = n;
queue<int> que;
que.push(start);
while(!que.empty()){
int node = que.front();
que.pop();
isInQueue[node]=false;//这个点已经出队了就标记false
//遍历以这个点为起点的所有节点
for(Edge edge : grid[node]){
int from = node;
int to = edge.to;
int value = edge.val;
if(minDist[to] > minDist[from] + value){
minDist[to] = minDist[from] + value;
if(isInQueue[to] == false){
que.push(to);
isInQueue[to] = true;
}
}
}
}
if(minDist[end] == INT_MAX) cout << "unconnected";
else cout << minDist[end];
return 0;
}