转自:http://www.cnblogs.com/pushing-my-way/archive/2012/08/05/2624271.html
spfa:
1.当给定的图存在负权边时,Dijkstra等算法便没有了用武之地,而Bellman-Ford算法的复杂度又过高,SPFA算法便派上用场了.
2.我们约定有向加权图G不存在负权回路,即最短路径一定存在
3.思路:
用数组d记录每个结点的最短路径估计值,而且用邻接表来存储图G。我们采取的方法是动态逼近法:设立一个先进先出的队列用来保存待优化的结点,优化时每次取出队首结点u,并且用u点当前的最短路径估计值对离开u点所指向的结点v进行松弛操作,如果v点的最短路径估计值有所调整,且v点不在当前的队列中,就将v点放入队尾。这样不断从队列中取出结点来进行松弛操作,直至队列空为止。
4.实现方法:
建立一个队列,初始时队列里只有起始点,在建立一个表格记录起始点到所有点的最短路径(该表格的初始值要赋为极大值,该点到他本身的路径赋为0)。然后执行松弛操作,用队列里有的点去刷新起始点到所有点的最短路,如果刷新成功且被刷新点不在队列中则把该点加入到队列最后。重复执行直到队列为空.
代码:
1 View Code 2 #include <iostream> 3 #include <memory.h> 4 #include <stdio.h> 5 #include <queue> 6 using namespace std; 7 const int maxp=1000; 8 const int maxe=1000; 9 const int maxnum=1000; 10 struct edge 11 { 12 int v; 13 int w; 14 int next; 15 }edge[maxe]; 16 17 typedef struct 18 { 19 int d; 20 int pre; 21 }pp; 22 pp point[maxp]; 23 int p,e; 24 25 queue<int> q; 26 bool use[maxp]; 27 28 void Init() 29 { 30 int i; 31 for(i=1;i<=p;i++) 32 { 33 point[i].d=maxnum; 34 point[i].pre=-1; 35 } 36 int u,v,w; 37 int index=1; 38 for(i=1;i<=e;i++) 39 { 40 cin>>u>>v>>w; 41 edge[index].v=v; 42 edge[index].w=w; 43 edge[index].next=point[u].pre; 44 point[u].pre=index; 45 index++; 46 } 47 } 48 49 void spfa(int s) 50 { 51 memset(use,false,sizeof(use)); 52 point[s].d=0; 53 q.push(s); 54 use[s]=true; 55 int t,i; 56 while(!q.empty()) 57 { 58 t=q.front(); 59 use[t]=false; 60 q.pop(); 61 for(i=point[t].pre;i!=-1;i=edge[i].next) 62 { 63 int v=edge[i].v; 64 int w=edge[i].w; 65 if(point[v].d>point[t].d+w) 66 { 67 point[v].d=point[t].d+w; 68 if(!use[v]) 69 { 70 q.push(v); 71 use[v]=true; 72 } 73 } 74 } 75 } 76 } 77 78 int main() 79 { 80 cin>>p>>e; 81 Init(); 82 spfa(1); 83 int i; 84 for(i=1;i<=p;i++) 85 cout<<i<<" "<<point[i].d<<endl; 86 return 0; 87 } 88 89 /* 90 5 10 91 1 2 10 92 1 3 5 93 2 3 2 94 2 4 1 95 3 2 3 96 3 4 9 97 3 5 2 98 4 5 4 99 5 1 7 100 5 4 6 101 */