浅谈spfa几个优化

优化一:每次更新节点时,记录当前走的这条路径的节点数,当节点数大于n时,有负环,退出。注意,这里与常规的节点被更新n次以上退出不一样,效率比常规高。

优化二:双端队列SLF优化。当当前节点到起点距离小于队首的时候,将此点插入队首,否则,正常插入队尾。可能咋一看感觉这种优化可能被用到的机会很少,但很可能正好解决掉了专门卡spfa的数据以及网格图。

优化三:与优化二类似,但改为小于队列元素平均数时加入队首,还没试过。

附上一道用spfa但以上优化效果很明显的一道题

http://codeforces.com/gym/101498/problem/L

不加优化2500ms左右(TLE边缘),加入优化一和优化二后311ms。

  1 #include <iostream>
  2 #include <fstream>
  3 #include <sstream>
  4 #include <cstdlib>
  5 #include <cstdio>
  6 #include <cmath>
  7 #include <string>
  8 #include <cstring>
  9 #include <algorithm>
 10 #include <queue>
 11 #include <stack>
 12 #include <vector>
 13 #include <set>
 14 #include <map>
 15 #include <list>
 16 #include <iomanip>
 17 #include <cctype>
 18 #include <cassert>
 19 #include <bitset>
 20 #include <ctime>
 21 
 22 using namespace std;
 23 
 24 #define pau system("pause")
 25 #define ll long long
 26 #define pii pair<int, int>
 27 #define pb push_back
 28 #define mp make_pair
 29 #define clr(a, x) memset(a, x, sizeof(a))
 30 
 31 const double pi = acos(-1.0);
 32 const int INF = 0x3f3f3f3f;
 33 const int MOD = 1e9 + 7;
 34 const double EPS = 1e-9;
 35 
 36 /*
 37 #include <ext/pb_ds/assoc_container.hpp>
 38 #include <ext/pb_ds/tree_policy.hpp>
 39 
 40 using namespace __gnu_pbds;
 41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
 42 */
 43 
 44 int T, n, m, u, v, c;
 45 map<pii, int> mmp;
 46 struct edge {
 47     int v, c;
 48     edge () {}
 49     edge (int v, int c) : v(v), c(c) {}
 50     bool operator < (const edge &e) const {
 51         return c < e.c;}
 52 };
 53 vector<edge> E[2015];
 54 ll spfa(int &flag) {
 55     bool in_que[2015];
 56     ll dis[2015];
 57     int cnt[2015];
 58 
 59     clr(in_que, 0);
 60     clr(cnt, 0);
 61     for (int i = 1; i <= n; ++i) {
 62         dis[i] = 1e18;
 63     }
 64     dis[0] = 0;
 65     deque<int> que;
 66     que.push_front(0);
 67 
 68     while (que.size()) {
 69         int x = que.front(); que.pop_front();
 70         in_que[x] = 0;
 71         for (int i = 0; i < E[x].size(); ++i) {
 72             int v = E[x][i].v, c = E[x][i].c;
 73             if (dis[v] > dis[x] + c) {
 74                 dis[v] = dis[x] + c;
 75                 if (!in_que[v]) {
 76                     if (que.size() && dis[v] < dis[que.front()] + 1) {
 77                         que.push_front(v);
 78                     } else {
 79                         que.push_back(v);
 80                     }
 81                     in_que[v] = 1;
 82                     cnt[v] = cnt[x] + 1;
 83                     if (n < cnt[v]) {
 84                         flag = 1;
 85                         return 2333;
 86                     }
 87                 }
 88             }
 89         }
 90     }
 91 
 92     ll ans = 1e18;
 93     for (int i = 1; i <= n; ++i) {
 94         ans = min(ans, dis[i]);
 95     }
 96     return ans;
 97 }
 98 int main() {
 99     scanf("%d", &T);
100     while (T--) {
101         scanf("%d%d", &n, &m);
102         mmp.clear();
103         int mi = 1e18;
104         for (int i = 1; i <= m; ++i) {
105             scanf("%d%d%d", &u, &v, &c);
106             if (mmp.count(pii(u, v))) {
107                 int x = mmp[pii(u, v)];
108                 c = min(x, c);
109             }
110             mmp[pii(u, v)] = c;
111             mi = min(mi, c);
112         }
113         if (mi >= 0) {
114             printf("%d
", mi);
115             continue;
116         }
117         for (int i = 1; i <= n; ++i) E[i].clear();
118         for (map<pii, int>::iterator it = mmp.begin(); it != mmp.end(); ++it) {
119             int u = (*it).first.first, v = (*it).first.second, c = (*it).second;
120             E[u].pb(edge(v, c));
121         }
122         for (int i = 1; i <= n; ++i) {
123             E[0].pb(edge(i, 0));
124         }
125         for (int i = 0; i <= n; ++i) {
126             sort(E[i].begin(), E[i].end());
127         }
128         int flag = 0;
129         ll ans = spfa(flag);
130         if (flag) {
131             puts("-inf");
132         } else {
133             printf("%lld
", ans);
134         }
135     }
136     return 0;
137 }
View Code
原文地址:https://www.cnblogs.com/BIGTOM/p/8776497.html