Dijkstra算法原理请见:最短路径问题(Dijkstra解法)
该算法对于稠密图更加有效:
对于给出具有非负权重的边和源顶点S的图G,算法可在O(mlogn)时间内找出从s点到其他每一个顶点的距离。
如果图是稠密的,即对于某个ε>0,m>=n^(1+ε),可以被改善在O(m/ε)内执行。(m为图的边数,n为图的定点数)
最小堆模板:
struct HeapElement {
// key存储顶点序号,value存储到该顶点的最短距离
int key, value;
};
struct MinHeap {
HeapElement heap[MAXN];
int position[MAXN];
int size; // 顶点数
void init() {
heap[size=0].value = -INF;
memset(position, 0, sizeof(position));
}
void insert(int key, int value) {
heap[++size].key = key;
heap[size].value = value;
position[key] = size;
siftUp(size);
}
void decrease(int index) {
int x = heap[index].value;
int y = heap[size].value;
-- size;
if (index == size+1)
return;
swap(heap[index], heap[size+1]);
if (y >= x) {
siftDown(index);
} else {
siftUp(index);
}
}
int delmin() {
int x = heap[1].key;
decrease(1);
return x;
}
void siftUp(int index) {
while (index > 1) {
if (heap[index].value < heap[index/2].value) {
swap(heap[index],heap[index/2]);
} else {
break;
}
index /= 2;
}
}
void siftDown(int index) {
while (index*2 <= size) {
index *= 2;
if (index < size && heap[index].value > heap[index+1].value) {
++ index;
}
if (heap[index].value < heap[index/2].value) {
swap(heap[index],heap[index/2]);
} else {
break;
}
}
}
void makeHeap() {
for (int i = size/2; i > 0; -- i)
siftDown(i);
}
void swap(HeapElement &a, HeapElement &b) {
HeapElement temp = a;
a = b;
b = temp;
int tmp = position[a.key];
position[a.key] = position[b.key];
position[b.key] = tmp;
}
}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\n",dist[N]);
}
}