spfa算法实际上是对bellman-ford算法进行了优化
spfa算法一定要求图中不含负环
dist[b]想变小,一定是dist[a]变小了
spfa用宽搜来做优化
队列里面就是所有变小的节点a,只要一个节点变小了,就把它放进队列里面然后去更新它的后继
spfa也可以适用于Dijkstra算法解决的题目
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 100010; 4 int h[N], e[N], w[N], ne[N], idx; 5 int dist[N]; 6 bool st[N]; 7 int n, m; 8 void add(int a, int b, int c) { 9 e[idx] = b; 10 w[idx] = c; 11 ne[idx] = h[a]; 12 h[a] = idx++; 13 } 14 int spfa() { 15 memset(dist, 0x3f, sizeof dist); 16 dist[1] = 0; 17 queue<int> q; 18 q.push(1); //把起点放进队列 19 st[1] = true; //st[] = true,表示这个点已经在队列中 20 while (q.size()) { //队列里面是所有变小的点 21 int t = q.front(); 22 q.pop(); //取出队头 23 st[t] = false; //点从队列中出来了,就false 24 for (int i = h[t]; i != -1; i = ne[i]) { //用t来更新其他所有边,遍历一下t的所有出边 25 //如果t变小了,所有以t为起点的边都有可能变小 26 int j = e[i]; 27 if (dist[j] > dist[t] + w[i]) { 28 dist[j] = dist[t] + w[i]; 29 if (!st[j]) { //如果队列里面已经有了,就不用重复加入了 30 q.push(j); //如果更新成功了,加进队列 31 st[j] = true; 32 } 33 //基本思路就是:更新过谁再拿谁更新别人 34 } 35 } 36 } 37 if (dist[n] == 0x3f3f3f3f) { 38 return -1; 39 } 40 return dist[n]; 41 } 42 int main() { 43 memset(h, -1, sizeof h); 44 cin >> n >> m; 45 while (m--) { 46 int a, b, c; 47 cin >> a >> b >> c; 48 add(a, b, c); 49 } 50 int t = spfa(); 51 if (t == -1) { 52 cout << "impossible" << endl; 53 } else { 54 cout << t << endl; 55 } 56 return 0; 57 }