使用最小堆优化Dijkstra算法

Posted 新参者

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用最小堆优化Dijkstra算法相关的知识,希望对你有一定的参考价值。

OJ5.2很简单,使用priority_queue实现了最小堆竟然都过了OJ……每次遇到relax的问题时都简单粗暴地重新push进一个节点……

然而正确的实现应该是下面这样的吧,关键在于swap堆中元素时使用pos数组存储改变位置后的编号为k的节点对应在堆中的位置。下面这种实现也很简单,d,v,p均存储在堆中,只有pos指明位置。源代码作者很聪明>_<

 

#include <stdio.h>

#define MAXN 1200
#define MAXM 1200000
#define INF 19930317

struct node
{
    int d, v, p;
}heap[MAXN];
int pos[MAXN], hl;

int e[MAXM], cost[MAXM], next[MAXM], g[MAXN], size;

int m, n, s, t;

void insert(int u, int v, int w)
{
    e[++size] = v;
    next[size] = g[u];
    cost[size] = w;
    g[u] = size;
}


void swap(int a, int b)
{
    heap[0] = heap[a];
    heap[a] = heap[b];
    heap[b] = heap[0];
    pos[heap[a].v] = a;
    pos[heap[b].v] = b;
}

void heapfy()
{
    int i = 2;
    while (i <= hl)
    {
        if ((i < hl) && (heap[i + 1].d < heap[i].d))
            i++;
        if (heap[i].d < heap[i >> 1].d)
        {
            swap(i, i >> 1);
            i <<= 1;
        }
        else
            break;
    }
}


void decrease(int i)
{
    while ((i != 1) && (heap[i].d < heap[i >> 1].d))
    {
        swap(i, i >> 1);
        i >>= 1;
    }
}

void relax(int u ,int v, int w)
{
    if (w + heap[pos[u]].d < heap[pos[v]].d)
    {
        heap[pos[v]].p = u;
        heap[pos[v]].d = w + heap[pos[u]].d;
        decrease(pos[v]);
    }
}

void delete_min()
{
    swap(1, hl);
    hl--;
    heapfy();
}

void init()
{
    int u ,v ,w, i;

    scanf("%d%d", &m, &n);
    for (i = 1; i <= m; i++)
    {
        scanf("%d%d%d", &u, &v, &w);
        insert(u, v, w);
        insert(v, u, w);
    }
    s = 1;
    t = n;
}

int dijkstra()
{
    int u, p, i;

    for (i = 1; i <= n; i++)
    {
        heap[i].v = pos[i] = i;
        heap[i].d = INF;
    }
    heap[s].p = s;
    heap[s].d = 0;
    swap(1, s);
    hl = n;
    while (hl)
    {
        u = heap[1].v;
        delete_min();
        p = g[u];
        while (p)
        {
            if (pos[e[p]] <= hl)
                relax(u, e[p], cost[p]);
            p = next[p];
        }

    }
}
int main() { init(); dijkstra(); printf("%d\n", heap[pos[t]].d); return 0; }

以上是关于使用最小堆优化Dijkstra算法的主要内容,如果未能解决你的问题,请参考以下文章

Dijkstra和堆优化

Dijkstra和堆优化

Luogu P4779dijkstra算法的堆优化

最短路-Dijkstra算法:朴素版&堆优化版(Java详解)

dijkstra算法的堆加速和暴力递归算法

图论 Dijkstra+堆优化