该算法对于稠密图更加有效:
对于给出具有非负权重的边和源顶点S的图G,算法可在O(mlogn)时间内找出从s点到其他每一个顶点的距离。
如果图是稠密的,即对于某个ε>0,m>=n^(1+ε),可以被改善在O(m/ε)内执行。(m为图的边数,n为图的定点数)
最小堆模板:
1 jfdkjfks
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)
#include <iostream> #define INF 0x7FFFFFFF using namespace std; const int SIZE = 105; int dist[SIZE]; int G[SIZE][SIZE]; bool vis[SIZE]; struct HeapElement { int key, value; }; void swap(HeapElement &ha, HeapElement &hb) { int key = ha.key; int value = ha.value; ha.key = hb.key; ha.value = hb.value; hb.key = key; hb.value = value; }; // 使用邻接表储存图,线性表储存堆 struct MinHeap { HeapElement heap[SIZE]; int n; // 顶点数 void makeheap() { for (int i = n/2; i > 0; -- i) siftDown(i); }; void siftUp(int index) { int k = index; while (k > 1) { if (heap[k].value < heap[k/2].value) { swap(heap[k],heap[k/2]); } else { break; } k /= 2; } }; void siftDown(int index) { int k = index; while (k*2 <= n) { k *= 2; if (k < n && heap[k].value > heap[k+1].value) { ++ k; } if (heap[k].value < heap[k/2].value) { swap(heap[k],heap[k/2]); } else { break; } } }; void insert(HeapElement element) { heap[++n] = element; siftUp(n); }; void decrease(int index) { int x = heap[index].value; int y = heap[n].value; n -= 1; // 若删除节点位于最末位置,则删除成功,无需其他操作。 if (index == n+1) return; heap[index] = heap[n+1]; if (y >= x) { siftDown(index); } else { siftUp(index); } }; int decreaseMin() { int x = heap[1].key; decrease(1); return x; }; }H; void dijkstra(int src, int n) { int i, j, w; bool flag; for (i = 1; i <= n; ++ i) { if (G[i][src] != INF) { dist[i] = G[src][i]; HeapElement h = {i, dist[i]}; H.insert(h); } else { dist[i] = INF; } } memset(vis, false, sizeof(vis)); vis[src] = true; dist[src] = 0; for (i = 1; i < n; ++ i) { int node = H.decreaseMin(); vis[node] = true; for (w = 1; w <= n; ++ w) { flag = false; if (!vis[w] && G[node][w] != INF) { if (dist[node] < dist[w] - G[node][w]) { dist[w] = dist[node] + G[node][w]; } for (j = 1; j <= H.n; ++ j) { if (H.heap[j].key == w) { H.heap[j].value = dist[w]; flag = true; break; } } if (!flag) { HeapElement h = {w, dist[w]}; H.insert(h); } else { H.siftUp(j); } } } } }; void init(int n) { for (int i = 1; i <= n; ++ i) for (int j = 1; j <= n; ++ j) G[i][j] = INF; H.n = 0; }; int main() { int N, M, a, b, c; //freopen("C:\Users\Smile\test.txt","r",stdin); //freopen("C:\Users\Smile\out.txt", "w", stdout); while (scanf("%d%d",&N,&M)!=EOF, N&&M) { init(N); for (int i = 0; i < M; ++ i) { scanf("%d%d%d",&a,&b,&c); if (G[a][b] > c) { G[a][b] = c; G[b][a] = c; } } dijkstra(1, N); printf("%d ",dist[N]); } }