SPFA算法模板

SPFA是队列优化后的Bellman-Ford,用于求带负权边的最短路,然而传说中O(k*n)的复杂度好像是错误的。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<string>
 5 #include<set>
 6 #include<queue>
 7 using namespace std;
 8 #define INF 0x3f3f3f3f
 9 #define M(a, b) memset(a, b, sizeof(a))
10 const int maxn = 1000 + 5;
11 
12 struct Edge {
13     int from, to, dist;
14 };
15 
16 struct SPFA {
17     int d[maxn], cnt[maxn], p[maxn];
18     int n, m;
19     bool inq[maxn];
20     vector<int> G[maxn];
21     vector<Edge> edges;
22 
23     void init(int n) {
24         this->n = n;
25         for (int i = 1; i <= n; ++i) G[i].clear();
26         edges.clear();
27     }
28 
29     void AddEdge(int from, int to, int dist) {
30         edges.push_back(Edge{from, to, dist});
31         int m = edges.size();
32         G[from].push_back(m-1);
33     }
34 
35     bool spfa(int s) {
36         M(d, INF); M(cnt, 0); M(inq, 0);
37         d[s] = 0;
38         queue<int> q;
39         q.push(s);
40         inq[s] = true;
41         while (!q.empty()) {
42             int u = q.front(); q.pop();
43             inq[u] = false;
44             for (int i = 0; i < G[u].size(); ++i) {
45                 Edge &e = edges[G[u][i]];
46                 if (d[e.to] > d[u] + e.dist) {
47                     d[e.to] = d[u] + e.dist;
48                     p[e.to] = G[u][i];
49                     if (!inq[e.to]) {
50                         q.push(e.to); inq[e.to] = true; 
51                         if (++cnt[e.to] > n) return false;
52                     }
53                 }
54             }
55         }
56         return true;
57     }
58 
59 };
60 
61 SPFA solver;
62 
63 int main() {
64     int n, m, a, b, c;
65     while(cin >> m >> n) {
66         solver.init(n);
67         while(m--) {
68             cin >> a >> b >> c;
69             solver.AddEdge(a, b, c);
70             solver.AddEdge(b, a, c);
71         }
72         solver.spfa(1);
73         cout << solver.d[n] << endl;
74     }
75     return 0;
76 }

 

转载于:https://www.cnblogs.com/robin1998/p/6602395.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值