poj 3159 heap+dijkstra

本文介绍了一种高效的最短路径算法实现方式,采用静态内存分配并利用堆优化Dijkstra算法,以快速找到图中两点之间的最短路径。该实现特别适用于边稠密的大规模有向图。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

思路:仔细看题,其实就是求1点到n点的最短路,图是有向的,时间卡的比较严,要用静态内存

 

  1. #include <iostream>
  2. #include <algorithm>
  3. using namespace std;
  4. const int N = 31000, M = 2500000, INF = 1000000000;
  5. #define left(x) ((x)<<1)
  6. #define right(x) (((x)<<1)+1)
  7. #define dad(x) ((x)>>1)
  8. struct data
  9. {
  10.     int id, w;
  11.     data *next;
  12. }mem[M];
  13. int mem_size, size, n, m;
  14. typedef data * node;
  15. node g[N];
  16. int dist[N], heap[3*N], map[N];
  17. node new_node(int id, int w)
  18. {
  19.     mem[mem_size++] = (data){id,w,0};
  20.     return mem+mem_size-1;
  21. }
  22. void heap_up(int root)
  23. {
  24.     int t=heap[root], fa=dad(root);
  25.     // hint: t = heap[root], not t = root
  26.     while(root!=1 && dist[t] < dist[heap[fa]])
  27.     {
  28.         heap[root] = heap[fa];
  29.         map[heap[root]] = root;
  30.         root = fa;
  31.         fa = dad(root);
  32.     }
  33.     heap[root] = t;
  34.     map[heap[root]] = root;
  35. }
  36. void heap_down(int root)
  37. {
  38.     int pos, t=heap[root], rc;
  39.     while((pos=left(root)) <= size)
  40.     {
  41.         rc = right(root);
  42.         if(rc <= size && dist[heap[rc]] < dist[heap[pos]]) pos  = rc;
  43.         if(dist[t] > dist[heap[pos]] )
  44.         {
  45.             heap[root] = heap[pos];
  46.             map[heap[root]] = root;
  47.         }
  48.         else break;
  49.         root = pos;
  50.     }
  51.     heap[root] = t;
  52.     map[heap[root]] = root;
  53. }
  54. int heap_pop()
  55. {
  56.     int t=heap[1];
  57.     heap[1]=heap[size--];
  58.     map[heap[1]] = 1;
  59.     heap_down(1);
  60.     return t;
  61. }
  62. int dijkstra(int s, int t)
  63. {
  64.     int i, j, k, u, v, tmp;
  65.     node p;
  66.     for(i = 1; i <= n; i++)
  67.     {
  68.         dist[i] = INF;
  69.         heap[i] = i;
  70.         map[i] = i;
  71.     }
  72.     size = n;
  73.     swap(heap[1],heap[s]);
  74.     swap(map[1],map[s]);
  75.     dist[s] = 0;
  76.     for(i = 1; i <= n; i++)
  77.     {
  78.         u = heap_pop();
  79.         for(p = g[u]->next; p; p = p->next)
  80.         {
  81.             j = dist[u] + p->w;
  82.             v = p->id;
  83.             if(j < dist[v])
  84.             {
  85.                 dist[v] = j;
  86.                 heap_up(map[v]);
  87.             }
  88.         }
  89.     }
  90.     return dist[t];
  91. }
  92. int main()
  93. {
  94.     int i, j, id, w;
  95.     node tmp;
  96.     scanf("%d%d", &n, &m);
  97.     mem_size=0;
  98.     size=0;
  99.     for(i = 1; i <= n; i++) g[i]= new_node(0,0);
  100.     // clear heap, map, dist, size if multiple tests
  101.     for(i = 0; i < m; i++)
  102.     {
  103.         scanf("%d%d%d",&j,&id,&w);
  104.         tmp = g[j]->next;
  105.         g[j]->next = new_node(id,w);
  106.         g[j]->next->next = tmp;
  107.     }
  108.     printf("%d/n", dijkstra(1, n));
  109.     return 0;
  110. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值