使用最小堆优化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;
}
时间: 2024-10-12 21:11:09

使用最小堆优化Dijkstra算法的相关文章

配对堆优化Dijkstra算法小记

关于配对堆的一些小姿势: 1.配对堆是一颗多叉树. 2.包含优先队列的所有功能,可用于优化Dijkstra算法. 3.属于可并堆,因此对于集合合并维护最值的问题很实用. 4.速度快于一般的堆结构(左偏树,斜堆,随机堆--),具体时间复杂度: 合并(Merge):$O(1)$: 插入(Insert/Push):$O(1)$: 修改值(Change):$O(1) \sim O(\log n)$: 取出维护的最值(Top):$O(1)$: 弹出堆顶元素(Pop):$O(\log n)$: 我们依然拿洛

EOJ 1848 你是ACM吗? 用二叉堆优化dijkstra + spfa算法的学习

Description  随着中国经济的腾飞,中国的物流产业迎来了发展的春天.特别是在上海这样一个拥有广阔国内腹地的国际化大都市,物流业以空前的速度膨胀. 当然是大蛋糕就会吸引许多馋嘴猫,馋嘴猫多了就会有残酷的竞争.当大量资金流入物流产业时,KOP 集团为了稳坐在国内物流业的第一把交椅,决定对现行的运输方案进行改良,以减少自己的成本同时使其它竞争者知难而退. 作为世界100强的KOP集团当然知道要找到最优运输方案,肯定得靠数学和算法很好的软件工程师,于是他们理所当然地找到华东师范大学软件学院.决

【bzoj4016】[FJOI2014]最短路径树问题 堆优化Dijkstra+DFS树+树的点分治

题目描述 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长度最短的路径,则选择经过的顶点序列字典序最小的那条路径(如路径A为1,32,11,路径B为1,3,2,11,路径B字典序较小.注意是序列的字典序的最小,而非路径中节点编号相连的字符串字典序最小).到达该点后按原路返回,然后往其他点走,直到所有点都走过. 可以知道,经过的边会构成一棵最短路径树.请问,在这棵最短路径树上,最长的包含K个点的简单路径长度为多长

【堆优化Dijkstra+字典序最短路方案】HDU1385-Minimum Transport Cost

[题目大意] 给出邻接矩阵以及到达各个点需要付出的代价(起点和终点没有代价),求出从给定起点到终点的最短路,并输出字典序最小的方案. [思路] 在堆优化Dijkstra中,用pre记录前驱.如果新方案和旧方案相等,比较两个方案的字典序. [坑点] 我先求出了最短路(包括终点要付出代价),输出的时候再减去终点的代价. 有可能会给出S==T的情况--在这种情况下,最短路就是0,减去代价要变成负数了QAQ所以要特判一下.坑了好几个小时orz 1 #include<iostream> 2 #inclu

【bzoj1097】[POI2007]旅游景点atr 状压dp+堆优化Dijkstra

题目描述 FGD想从成都去上海旅游.在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情.经过这些城市的顺序不是完全随意的,比如说FGD不希望在刚吃过一顿大餐之后立刻去下一个城市登山,而是希望去另外什么地方喝下午茶.幸运的是,FGD的旅程不是既定的,他可以在某些旅行方案之间进行选择.由于FGD非常讨厌乘车的颠簸,他希望在满足他的要求的情况下,旅行的距离尽量短,这样他就有足够的精力来欣赏风景或者是泡MM了^_^.整个城市交通网络包含N个城市以及城市与城市之间的双向道路M条

BZOJ 2118 墨墨的等式 堆优化Dijkstra

题目大意:给定n个物品,每个物品有一个非负价值,问[L,R]区间内有多少价值可以被凑出来 好题!!! 如果物品数量可以为负,显然求个gcd就行了 现在物品数量必须非负 任选一个ai>0,如果一个价值k?ai+x(0≤x<ai,k≥0)可以被凑出来,那么显然(k+1)?ai+x,(k+2)?ai+x,...都可以被凑出来 显然如果我们对于每个x都找到最小的k满足k?ai+x可以被凑出来,这个问题就解决了 那么怎么求呢?最短路,使用堆优化Dijkstra即可 时间复杂度O(n?ai?log2ai)

BZOJ3040 最短路 (堆优化dijkstra)

这题不是裸的最短路么?但是一看数据范围就傻了.点数10^6,边数10^7.这个spfa就别想了(本来spfa就是相当不靠谱的玩意),看来是要用堆优化dijkstra了.但是,平时写dijkstra时为了偷懒直接用的STL的priority_queue,没办法改变权值,所以都是直接把pair压进堆里.然后时间复杂度O(mlogm),空间复杂度O(m),不靠谱.手写二叉堆?改变权值是O(logn)的,所以时间复杂度O(mlogn),空间复杂度O(n),还是要T.看来是需要一种比较牛逼的堆了. Fib

【bzoj3073】[Pa2011]Journeys 线段树优化建图+堆优化Dijkstra

题目描述 Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建造道路:(a,b),(c,d)表示,对于任意两个国家x,y,如果a<=x<=b,c<=y<=d,那么在xy之间建造一条道路.Seter保证不会有一个国家与自己之间有道路. Seter好不容易建好了所有道路,他现在在位于P号的首都.Seter想知道P号国家到任意一个国家最少需要经过几条道路.当然,Se

POJ 3013 Big Christmas Tree【最短路变形,DIjkstra堆优化+spfa算法】

Big Christmas Tree Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 23064   Accepted: 4987 Description Christmas is coming to KCM city. Suby the loyal civilian in KCM city is preparing a big neat Christmas tree. The simple structure of t