11.spfa求最短路

 

 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 }

 

posted @ 2020-07-25 02:47  kyk333  阅读(154)  评论(0)    收藏  举报