Spfa算法——最短路径问题
SPFA原理
设立一个先进先出的队列用来保存待优化的结点,优化时每次取出队首结点u,并且用u点当前的最短路径估计值对离开u点所指向的结点v进行松弛操作,如果v点的最短路径估计值有所调整,且v点不在当前的队列中,就将v点放入队尾。这样不断从队列中取出结点来进行松弛操作,直至队列空为止。
洛谷链接:https://www.luogu.org/problem/show?pid=3371
´Spfa算法实际上是对于bellman-ford算法的一个使用队列的优化。
´我们不再同时对m条边进行松弛,而是选择将每次松弛后的到达的点加入队列(如果已经在 队列就可以忽略),然后再去松弛由这个点连出去的边
´对于负环的判断,实际上只需要出现某一个点进入队列n次,就可以知道出现了负环。
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <queue> 5 #include <vector> 6 #include <string.h> 7 using namespace std; 8 #define uint unsigned int 9 #define ll long long 10 #define ull unsigned ll 11 #define pii pair<int,int> 12 #define pb push_back 13 #define mp make_pair 14 #define INF 2147483647 15 #define LINF 9999999999 16 #define ms(l) memset(l,0,sizeof(l)) 17 18 uint n,m,spoint; 19 uint dis[10001]; 20 class Edge{ 21 public: 22 uint to,cost; 23 }; 24 vector<Edge> data[10000]; 25 26 void addedge(uint fr,uint to,uint co){ 27 Edge e1; 28 e1.to = to; e1.cost = co; 29 data[fr].pb(e1); 30 } 31 32 void spfa(void){ 33 queue<uint> q; bool at[10001]; 34 q.push(spoint); ms(at); 35 for(uint i = 1;i <= n;i++) 36 dis[i] = INF; 37 dis[spoint] = 0; at[spoint] = 1; 38 while(!q.empty()){ 39 uint u; 40 u = q.front(); 41 q.pop(); at[u] = 0; 42 for(uint i = 0;i < data[u].size();i++) 43 if(dis[u]+data[u][i].cost < dis[data[u][i].to]){ 44 dis[data[u][i].to] = dis[u]+data[u][i].cost; 45 if(!at[data[u][i].to]){ 46 at[data[u][i].to] = 1; 47 q.push(data[u][i].to); 48 } 49 } 50 } 51 } 52 int main(){ 53 //freopen("i.txt","r",stdin); 54 cin >> n >> m >> spoint; 55 for(uint i = 1;i <= m;i++){ 56 uint f,t,c; 57 cin >> f >> t >> c; 58 addedge(f,t,c); 59 } 60 spfa(); 61 for(uint i = 1;i <= n;i++) 62 cout << dis[i] << ' '; 63 cout << endl; 64 return 0; 65 }
推荐:http://www.360doc.com/content/13/1208/22/14357424_335569176.shtml