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

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

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

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

11876kB30ms

好了,记录一下我的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

转载于:https://www.cnblogs.com/LyonLys/archive/2012/05/14/priority_queue_Dij_Lyon.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是使用堆优化Dijkstra 算法来求解最短路径的示例代码,其中使用了 vector 来表示图的邻接表: ```cpp #include <iostream> #include <vector> #include <queue> #include <limits> using namespace std; typedef pair<int, int> pii; const int INF = numeric_limits<int>::max(); vector<int> dijkstra(const vector<vector<pii>>& graph, int source) { int n = graph.size(); vector<int> dist(n, INF); dist[source] = 0; priority_queue<pii, vector<pii>, greater<pii>> pq; pq.push({0, source}); while (!pq.empty()) { int u = pq.top().second; int d = pq.top().first; pq.pop(); if (d > dist[u]) { continue; // 已经找到了更短的路径 } for (const auto& edge : graph[u]) { int v = edge.first; int w = edge.second; if (dist[u] + w < dist[v]) { dist[v] = dist[u] + w; pq.push({dist[v], v}); } } } return dist; } int main() { int n = 5; // 图的顶点数 int m = 7; // 图的边数 vector<vector<pii>> graph(n); // 构建图的邻接表 graph[0].push_back({1, 2}); graph[0].push_back({2, 4}); graph[1].push_back({2, 1}); graph[1].push_back({3, 7}); graph[2].push_back({3, 3}); graph[2].push_back({4, 5}); graph[3].push_back({4, 2}); graph[4].push_back({3, 1}); int source = 0; vector<int> dist = dijkstra(graph, source); cout << "Shortest distances from node " << source << ":" << endl; for (int i = 0; i < n; ++i) { cout << "Node " << i << ": " << dist[i] << endl; } return 0; } ``` 上述代码中,我们使用堆优化Dijkstra 算法来找到从源节点到其他节点的最短距离。图的邻接关系使用 vector<vector<pii>> 来表示,其中 pii 表示边的目标节点和权重。你可以根据需要修改图的顶点数、边数和邻接表来适应不同的场景。输出结果将会显示源节点到其他节点的最短距离。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值