hud2544dijkstra+堆优化

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

对于给出具有非负权重的边和源顶点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\n",dist[N]);    
    }
}

  

 

posted @ 2016-04-26 11:49  zach96  阅读(242)  评论(0编辑  收藏  举报