与迪杰斯特拉相同的是spfa也是用来求单源点的最短路径问题,但是,当问题中的边是有向负边的时候,迪杰斯特拉就无能为力了,
而且给我的感觉是spfa如何结合STL来用的话代码比迪杰斯特拉的还要短一点,只是在思路上会比它稍微复杂一点点。spfa的原理:
同样设置一个数组d[maxn]用来保存源点到各点的距离,初始化为无穷打,同时定义一个队列que,初始化为空,然后还要定义一个数组visit[maxn],
用来标记当前的某个点是否在队列当中,初始化为false。算法第一步,把源点加入到队列中,然后用源点去更新源点到它可以到达的点的距离,
如果这个源点到这个点的距离可以被更新,而且队列中没有这个点的话,就把这个点加入到队列中。然后继续从队首弹出一个点,然后同理用这个点
去更新其它的点,重复下去直到队列为空,这时结果就出来了。下面是我A的第一个spfa的代码,用邻接表的,小小的纪念一下。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<deque> 6 using namespace std; 7 8 typedef struct node 9 { 10 int d,len; 11 node *next; 12 }Linklist; 13 typedef struct Node 14 { 15 int tot; 16 Linklist *next; 17 Node() 18 { 19 tot = 0; 20 next = NULL; 21 } 22 }linklist; 23 linklist rode[20005]; 24 25 int d[20005],visit[20005]; 26 void push(int u,int v,int l) 27 { 28 Linklist *q = new Linklist; 29 q->d = v; 30 q->len = l; 31 q->next = NULL; 32 rode[u].tot++; 33 if(rode[u].next == NULL) 34 { 35 rode[u].next = q; 36 return ; 37 } 38 Linklist *p = rode[u].next; 39 while(p->next) 40 p = p->next; 41 p->next = q; 42 } 43 44 int main() 45 { 46 int n,m,u,v,l; 47 scanf("%d%d",&n,&m); 48 for(int i = 0;i < m;++i) 49 { 50 scanf("%d%d%d",&u,&v,&l); 51 push(u,v,l); 52 } 53 deque<int> que; 54 deque<int>::iterator iter; 55 que.push_back(1); 56 memset(d,0x3f,sizeof(d)); 57 memset(visit,0,sizeof(visit)); 58 visit[1] = 1; 59 d[1] = 0; 60 while(!que.empty()) 61 { 62 int temp = *(que.begin()); 63 que.pop_front(); 64 visit[temp] = 0; 65 Linklist *p = rode[temp].next; 66 while(p) 67 { 68 if(d[temp] + p->len < d[p->d]) 69 { 70 d[p->d] = d[temp] + p->len; 71 if(!visit[p->d]) 72 { 73 que.push_back(p->d); 74 visit[p->d] = 1; 75 } 76 } 77 p = p->next; 78 } 79 } 80 for(int i = 2;i <= n;++i) 81 printf("%d\n",d[i]); 82 return 0; 83 }