SPFA 算法是 bellman 的队列优化算法的别称,通常用于求含负权边的单源最短路径,以及判负权环。SPFA 最坏情况下复杂度和朴素 Bellman-Ford 相同

和bellman一样可以用来判断负环

 1 int first[N];
 2 struct Edge{
 3     int to;
 4     int next;
 5     int w;
 6 }edge[N];
 7 int cnt=0;
 8 void add(int u,int v,int w){
 9     edge[++cnt].to=v;
10     edge[cnt].w=w;
11     edge[cnt].next=first[u];
12     first[u]=cnt;
13 }
14 int dis[N];
15 int main(){
16     ioscin;
17     int n,m,s;
18     cin>>n>>m>>s;
19     memset(dis,127,sizeof(dis));
20     dis[s]=0;
21     while(m--){
22         int u,v,w;
23         cin>>u>>v>>w;
24         add(u,v,w);
25     }
26     queue<int>q;
27     int cnt=0;
28     for(!q.empty()){
29         cnt++;
30         int num=0;
31         int i=q.front();
32         q.pop();
33         for(int j=first[i];j!=0;j=edge[j].next){
34             if(dis[edge[j].to]>dis[i]+edge[j].w){
35                 num++;
36                 dis[edge[j].to]=dis[i]+edge[j].w;
37                 q.push(edge[j].to);
38             }
39         }
40         if(num==0){
41             break;
42         }
43         if(cnt>=n){
44             cout<<"有负环";
45         }
46     }
47     for(int i=1;i<=n;++i){
48         cout<<dis[i]<<' ';
49     }
50     return 0;
51 }//spfa优化

flody快速求各点到各点的最短路;

 1 int dis[N][N];
 2 int main(){
 3     int n,m;
 4     cin>>n>>m;
 5     memset(dis,127,sizeof(dis));
 6     while(m--){
 7         int a,b,c;
 8         cin>>a>>b>>c;
 9         dis[a][b]=c;
10         dis[b][a]=c;
11     }
12     for(int i=1;i<=n;++i){
13         dis[i][i]=0;
14     }
15     for(int i=1;i<=n;++i){
16         for(int j=1;j<=n;++j){
17             for(int k=1;k<=n;++k){
18                 if(dis[i][j]>dis[i][k]+dis[k][j]){
19                     dis[i][j]=dis[i][k]+dsi[k][j];
20                 }
21             }
22         }
23     }
24     return 0;
25 }//floyd

分层图就是多建边,将所有情况全部列出来

 1 #include<iostream>
 2 using namespace std;
 3 #include<cstring>
 4 #include<iomanip>
 5 #include<vector>
 6 #include<cmath>
 7 #include<queue>
 8 #include<string>
 9 #include<algorithm>
10 #include<set>
11 #include<map>
12 #include<stack>
13 #define ll long long
14 #define all(x) (x).begin(), (x).end()
15 #define pb push_back
16 #define pii pair<int, int>
17 #define pll pair<long long, long long>
18 #define mp make_pair
19 #define ioscin ios_base::sync_with_stdio(false);cin.tie(NULL)
20 #define lb lower_bound
21 #define ub upper_bound
22 const int N = 1e6 + 20;
23 int n, m, k;
24 struct Edge {
25     int to;
26     int next;
27     int w;
28 }e[N];
29 int cnt = 0;
30 int first[N];
31 void add(int u, int v, int w) {
32     e[++cnt].w = w;
33     e[cnt].to = v;
34     e[cnt].next = first[u];
35     first[u] = cnt;
36 }
37 int dis[N];
38 int vis[N];
39 priority_queue<pii>q;
40 void dijk(int s) {
41     memset(dis, 127, sizeof(dis));
42     dis[s] = 0;
43     vis[s]=1;
44     q.push(mp(dis[s], s));
45     while (!q.empty()) {
46         int w = q.top().first;
47         int x = q.top().second;
48         q.pop();
49         if (dis[x] != w)
50             continue;
51         for (int i = first[x]; i; i = e[i].next) {
52             if (!vis[e[i].to]&&dis[e[i].to] > dis[x] + e[i].w) {
53                 dis[e[i].to] = dis[x] + e[i].w;
54                 q.push(mp(dis[e[i].to], e[i].to));
55             }
56         }
57     }
58 }
59 int main() {
60     ioscin;
61     cin >> n >> m >> k;
62     while (m--) {
63         int a, b, c;
64         cin >> a >> b >> c;
65         add(a, b, c);
66         add(b, a, c);
67         for (int i = 1; i <= k; ++i) {
68             add(a + n * i, b + n * i, c);
69             add(b + n * i, a + n * i, c);
70             add(a + (i - 1) * n, b + n * i, c/2);
71             add(b + (i - 1) * n, a + n * i, c/2);
72         }//重点是这一段建边
73     }
74     dijk(1);
75     int ans = dis[n];
76     for (int i = 1; i <= k; ++i) {
77         ans = min(ans, dis[n+i*n]);
78     }
79     cout << ans << endl;
80     return 0;
81 }

//此题对应洛谷https://www.luogu.com.cn/problem/P4822