Dijkstra + 堆优化

来源:互联网 发布:jqueryeach遍历数组 编辑:程序博客网 时间:2024/05/17 14:20

Dijkstra算法原理请见:最短路径问题(Dijkstra解法)


该算法对于稠密图更加有效:

对于给出具有非负权重的边和源顶点S的图G,算法可在O(mlogn)时间内找出从s点到其他每一个顶点的距离。

如果图是稠密的,即对于某个ε>0,m>=n^(1+ε),可以被改善在O(m/ε)内执行。(m为图的边数,n为图的定点数)


最小堆模板:

[cpp] view plain copy
  1. struct HeapElement {  
  2.     // key存储顶点序号,value存储到该顶点的最短距离   
  3.     int key, value;  
  4. };  
  5. struct MinHeap {  
  6.     HeapElement heap[MAXN];  
  7.     int position[MAXN];  
  8.     int size; // 顶点数  
  9.     void init() {   
  10.         heap[size=0].value = -INF;   
  11.         memset(position, 0, sizeof(position));  
  12.     }  
  13.     void insert(int key, int value) {  
  14.         heap[++size].key = key;  
  15.         heap[size].value = value;  
  16.         position[key] = size;  
  17.         siftUp(size);  
  18.     }  
  19.     void decrease(int index) {  
  20.         int x = heap[index].value;  
  21.         int y = heap[size].value;  
  22.         -- size;  
  23.         if (index == size+1)  
  24.             return;  
  25.           
  26.         swap(heap[index], heap[size+1]);  
  27.         if (y >= x) {  
  28.             siftDown(index);      
  29.         } else {  
  30.             siftUp(index);    
  31.         }  
  32.     }  
  33.     int delmin() {  
  34.         int x = heap[1].key;  
  35.         decrease(1);  
  36.         return x;  
  37.     }  
  38.     void siftUp(int index) {  
  39.         while (index > 1) {  
  40.             if (heap[index].value < heap[index/2].value) {  
  41.                 swap(heap[index],heap[index/2]);      
  42.             } else {  
  43.                 break;  
  44.             }  
  45.             index /= 2;  
  46.         }  
  47.     }  
  48.     void siftDown(int index) {  
  49.         while (index*2 <= size) {  
  50.             index *= 2;  
  51.             if (index < size && heap[index].value > heap[index+1].value) {  
  52.                 ++ index;  
  53.             }  
  54.             if (heap[index].value < heap[index/2].value) {  
  55.                 swap(heap[index],heap[index/2]);  
  56.             } else {  
  57.                 break;  
  58.             }  
  59.         }  
  60.     }  
  61.     void makeHeap() {  
  62.         for (int i = size/2; i > 0; -- i)   
  63.             siftDown(i);  
  64.     }  
  65.     void swap(HeapElement &a, HeapElement &b) {  
  66.         HeapElement temp = a;  
  67.         a = b;  
  68.         b = temp;  
  69.         int tmp = position[a.key];  
  70.         position[a.key] = position[b.key];  
  71.         position[b.key] = tmp;  
  72.     }  
  73. }H;  


代码实现:(hdu2544)

[cpp] view plain copy
  1. #include <iostream>  
  2. #define INF 0x7FFFFFFF  
  3. using namespace std;  
  4.   
  5. const int SIZE = 105;  
  6. int dist[SIZE];  
  7. int G[SIZE][SIZE];  
  8. bool vis[SIZE];  
  9. struct HeapElement {  
  10.     int key, value;      
  11. };  
  12. void swap(HeapElement &ha, HeapElement &hb) {  
  13.     int key = ha.key;  
  14.     int value = ha.value;  
  15.     ha.key = hb.key;  
  16.     ha.value = hb.value;  
  17.     hb.key = key;  
  18.     hb.value = value;  
  19. };  
  20. // 使用邻接表储存图,线性表储存堆   
  21. struct MinHeap {  
  22.     HeapElement heap[SIZE];  
  23.     int n;    // 顶点数      
  24.           
  25.     void makeheap() {  
  26.         for (int i = n/2; i > 0; -- i)  
  27.             siftDown(i);  
  28.     };  
  29.     void siftUp(int index) {  
  30.         int k = index;  
  31.         while (k > 1) {  
  32.             if (heap[k].value < heap[k/2].value) {  
  33.                 swap(heap[k],heap[k/2]);      
  34.             } else {  
  35.                 break;      
  36.             }  
  37.             k /= 2;      
  38.         }  
  39.     };  
  40.     void siftDown(int index) {  
  41.         int k = index;  
  42.         while (k*2 <= n) {  
  43.             k *= 2;  
  44.             if (k < n && heap[k].value > heap[k+1].value) {  
  45.                 ++ k;      
  46.             }  
  47.             if (heap[k].value < heap[k/2].value) {  
  48.                 swap(heap[k],heap[k/2]);  
  49.             } else {  
  50.                 break;      
  51.             }      
  52.         }  
  53.     };  
  54.     void insert(HeapElement element) {  
  55.         heap[++n] = element;  
  56.         siftUp(n);      
  57.     };  
  58.     void decrease(int index) {  
  59.         int x = heap[index].value;  
  60.         int y = heap[n].value;  
  61.         n -= 1;  
  62.           
  63.         // 若删除节点位于最末位置,则删除成功,无需其他操作。   
  64.         if (index == n+1)   
  65.             return;  
  66.           
  67.         heap[index] = heap[n+1];  
  68.         if (y >= x) {  
  69.             siftDown(index);      
  70.         } else {  
  71.             siftUp(index);      
  72.         }  
  73.     };  
  74.     int decreaseMin() {  
  75.         int x = heap[1].key;  
  76.         decrease(1);  
  77.         return x;  
  78.     };  
  79. }H;  
  80.   
  81. void dijkstra(int src, int n) {  
  82.     int i, j, w;  
  83.     bool flag;  
  84.       
  85.     for (i = 1; i <= n; ++ i) {  
  86.         if (G[i][src] != INF) {  
  87.             dist[i] = G[src][i];  
  88.             HeapElement h = {i, dist[i]};  
  89.             H.insert(h);      
  90.         } else {  
  91.             dist[i] = INF;      
  92.         }      
  93.     }  
  94.       
  95.     memset(vis, falsesizeof(vis));  
  96.     vis[src] = true;  
  97.     dist[src] = 0;  
  98.       
  99.   
  100.       
  101.     for (i = 1; i < n; ++ i) {  
  102.   
  103.         int node = H.decreaseMin();  
  104.         vis[node] = true;  
  105.   
  106.         for (w = 1; w <= n; ++ w) {  
  107.             flag = false;  
  108.             if (!vis[w] && G[node][w] != INF) {  
  109.                 if (dist[node] < dist[w] - G[node][w]) {  
  110.                     dist[w] = dist[node] + G[node][w];  
  111.                           
  112.                 }   
  113.                 for (j = 1; j <= H.n; ++ j) {  
  114.                         if (H.heap[j].key == w) {  
  115.                             H.heap[j].value = dist[w];  
  116.                             flag = true;  
  117.                             break;      
  118.                         }      
  119.                     }      
  120.                   
  121.                 if (!flag) {  
  122.                     HeapElement h = {w, dist[w]};  
  123.                     H.insert(h);  
  124.                 } else {  
  125.                     H.siftUp(j);  
  126.                 }  
  127.             }  
  128.         }      
  129.     }  
  130. };  
  131.   
  132. void init(int n) {  
  133.     for (int i = 1; i <= n; ++ i)  
  134.         for (int j = 1; j <= n; ++ j)  
  135.             G[i][j] = INF;  
  136.     H.n = 0;  
  137. };  
  138.   
  139. int main()  
  140. {  
  141.     int N, M, a, b, c;  
  142.       
  143.     //freopen("C:\\Users\\Smile\\test.txt","r",stdin);  
  144.     //freopen("C:\\Users\\Smile\\out.txt", "w", stdout);  
  145.       
  146.     while (scanf("%d%d",&N,&M)!=EOF, N&&M) {  
  147.         init(N);  
  148.           
  149.         for (int i = 0; i < M; ++ i) {  
  150.             scanf("%d%d%d",&a,&b,&c);  
  151.             if (G[a][b] > c) {  
  152.                 G[a][b] = c;  
  153.                 G[b][a] = c;  
  154.             }  
  155.         }  
  156.           
  157.         dijkstra(1, N);  
  158.           
  159.         printf("%d\n",dist[N]);      
  160.     }  

0 0
原创粉丝点击