学了一下dij+heap
用它做了做HDU2544
遇到了两个问题:
1.堆数组H开的太小会RE
2.对于该题跑时15ms, 不加优化15ms,spfa跑时0ms
探究:
1.对于第一个问题:结点是会被重复加入的。因为每次松弛时,都会有结点加入堆,因此加入堆的结点总数会大于总的结点数。
2.对于第二个问题,在网上找了找资料,迷茫中闪现一丝曙光。资料地址:http://blog.csdn.net/lyso1/article/details/5687180
#include <stdio.h> #include <string.h> #include <stdlib.h> #define MAXN 106 #define INF (1<<20) int d[MAXN], w[MAXN][MAXN]; unsigned char vis[MAXN]; int cmp(int i, int j){ return d[i]>d[j]; } void swap(int A[], int i, int j){ int t = A[i]; A[i] = A[j]; A[j] = t; } void Heap_init(int A[]){ A[0] = 0; } int heap_empty(int A[]){ return A[0] == 0; } void heap_insert(int A[], int x){ int i = ++A[0]; A[A[0]] = x; while(i != 1){ if(!cmp(A[i], A[i/2])) swap(A, i, i/2); else break; i /= 2; } } int delete_min(int A[]){ int x = A[1], y = A[A[0]], i = 1; A[0]--; if(A[0] >= 1){ A[1] = y; while((i*=2) <= A[0]){ if(i+1<=A[0] && !cmp(A[i+1],A[i])) i++; if(cmp(A[i/2], A[i])) swap(A, i/2, i); else break; } } return x; } void Dijkstra(int v0, int n){ int H[2000], i, y; Heap_init(H); for(i=0; i<n; i++){d[i] = INF; vis[i] = 0;} d[v0]=0; heap_insert(H, v0); while(!heap_empty(H)){ int x; x = delete_min(H); if(!vis[x]){ vis[x] = 1; for(y=0; y<n; y++){ if(d[y] > d[x] + w[x][y]){ d[y] = d[x] + w[x][y]; heap_insert(H, y); } } } } } int main(){ int n, m, a, b, c, i, j; while(scanf("%d %d", &n, &m) == 2 && (n != 0 || m != 0)){ for(i=0; i<n; i++){ for(j=0; j<n; j++) w[i][j] = INF; } for(i=0; i<m; i++){ scanf("%d %d %d", &a, &b, &c); w[a-1][b-1] = w[b-1][a-1] = c; } Dijkstra(0, n); printf("%d\n", d[n-1]); } return 0; }