• 用优先队列优化Dij的一个代码


      以前看过SPFA的解释,看懂了却一直没有尝试着写出来。今天见到一题100000个点1000000条边的最短路问题,看到边数相对点来说是非常少的,所以我第一反应就是用Dij来做。但是考虑到普通的Dij写这个10^6条边的代码是带不动的,于是我突然想起了好像可以用优先队列来对此优化,这种优化方法叫做SPFA(纠正一下,应该说这种方法跟SPFA类似,但SPFA是对Bellman的普通队列优化)我没有再去看SPFA的伪代码或者模板,只是凭自己对优先队列的用法来尝试着写这个优先队列优化的Dij,自己算过,理论时间复杂度是O(ke),e是边的数目,k不超过2。

      由于是第一次写这个代码,中间出现好多错误,例如,忘记检查队列是否为空而直接用pop和top。

      最后打完后测试了几组数据,都OK了。于是我就交上去,除了内存开销比较大,时间是相当理想的:

    11876kB 30ms

    好了,记录一下我的1Y代码吧!

    View Code
      1 #include "cstdio"
      2 #include "cstdlib"
      3 #include "cstring"
      4 #include "cmath"
      5 #include "cctype"
      6 #include "vector"
      7 #include "set"
      8 #include "map"
      9 #include "string"
     10 #include "algorithm"
     11 #include "stack"
     12 #include "queue"
     13 
     14 #define INF 0x7fffffff
     15 #define reset(a) memset(a, 0, sizeof(a))
     16 #define copy(a, b) memcpy(a, b, sizeof(b))
     17 #define PI acos(-1)
     18 #define FMAX (1E300)
     19 #define MAX 1000000000
     20 #define feq(a, b) (fabs((a)-(b))<1E-6)
     21 #define flq(a, b) ((a)<(b)||feq(a, b))
     22 #define MAXN 10005
     23 #define BASE 137
     24 #define PASS puts("pass")
     25 #define filein freopen("test.in", "r", stdin)
     26 #define fileout freopen("test.out", "w", stdout)
     27 
     28 using namespace std;
     29 
     30 struct Point{
     31     int p;
     32     int d;
     33     bool operator < (const Point &x) const{
     34         return d > x.d;
     35     }
     36 };
     37 struct Edge{
     38     int b;
     39     int e;
     40     int d;
     41     bool operator < (const Edge &x) const{
     42         return b < x.b;
     43     }
     44     bool operator == (const Edge &x) const{
     45         return b == x.b;
     46     }
     47 }e[1000000];
     48 priority_queue<Point, vector<Point>, less<Point> >Q;
     49 int v[100001];
     50 bool vis[100001];
     51 
     52 int main(){
     53     int n, m;
     54     //filein;
     55     //fileout;
     56     pair<Edge *, Edge *> p;
     57 
     58     while (~scanf("%d%d", &n, &m)){
     59         reset(e);
     60         reset(vis);
     61 
     62         while (Q.size())
     63             Q.pop();
     64         vis[1] = true;
     65         v[1] = 0;
     66         for (int i = 2; i <= n; i++)
     67             v[i] = MAX;
     68 
     69         for (int i = 0; i < m; i++)
     70             scanf("%d%d%d", &e[i].b, &e[i].e, &e[i].d);
     71         sort(e, e + m);
     72 
     73         int cur = 1;
     74         Edge te;
     75         Point tp;
     76 
     77         tp = {1, 0};
     78         Q.push(tp);
     79         while (Q.size() && cur != n){
     80             te.b = cur;
     81             p = equal_range(e, e + m, te);
     82             //printf("search  %d  %d\n", p.first - e, p.second - e);
     83             for (int i = p.first - e, end = p.second - e; i < end; i++){
     84                 if (v[e[i].e] > v[e[i].b] + e[i].d){
     85                     v[e[i].e] = v[e[i].b] + e[i].d;
     86                     if (!vis[e[i].e]){
     87                         tp = {e[i].e, v[e[i].e]};
     88                         Q.push(tp);
     89                         //PASS;
     90                     }
     91                 }
     92             }
     93             while (Q.size() && vis[Q.top().p]){
     94                 Q.pop();
     95             }
     96             if (Q.size()){
     97                 cur = Q.top().p;
     98                 vis[cur] = true;
     99                 Q.pop();
    100             }
    101         }
    102         printf("%d\n", v[n]);
    103     }
    104 
    105     return 0;
    106 }

    ——written by Lyon

  • 相关阅读:
    ftp
    vmware虚拟机如何安装ubuntu14.10系统
    第1章 初识java----Java简介
    fiddler
    Program Files 与Program Files (x86)
    跟我一起认识axure(三)
    React-FlipOver-Counter(日历翻页)
    vue2-vux-fitness-project
    cloud-music
    跟我一起认识axure(二)
  • 原文地址:https://www.cnblogs.com/LyonLys/p/priority_queue_Dij_Lyon.html
Copyright © 2020-2023  润新知