Dijkstra+heap的标程(很短很精炼,不过看懂不容易)

//单源最短路径,dijkstra算法+映射二分堆,邻接表形式,复杂度O(mlogn)
//求出源s到所有点的最短路经,传入图的大小n和邻接表list
//返回到各点最短距离min[]和路径pre[],pre[i]记录s到i路径上i的父结点,pre[s]=-1
//可更改路权类型,但必须非负!
#define MAXN 200
#define inf 1000000000
typedef int elem_t;
struct edge_t{
    int from,to;
    elem_t len;
    edge_t* next;
};
 
#define _cp(a,b) ((a)<(b))
struct heap{
    elem_t h[MAXN+1];
    int ind[MAXN+1],map[MAXN+1],n,p,c;
    void init(){n=0;}
    void ins(int i,elem_t e){
        for (p=++n;p>1&&_cp(e,h[p>>1]);h[map[ind[p]=ind[p>>1]]=p]=h[p>>1],p>>=1);
        h[map[ind[p]=i]=p]=e;
    }
    int del(int i,elem_t& e){
        i=map[i];if (i<1||i>n) return 0;
        for (e=h[p=i];p>1;h[map[ind[p]=ind[p>>1]]=p]=h[p>>1],p>>=1);
        for (c=2;c<n&&_cp(h[c+=(c<n-1&&_cp(h[c+1],h[c]))],h[n]);h[map[ind[p]=ind[c]]=p]=h[c],p=c,c<<=1);
        h[map[ind[p]=ind[n]]=p]=h[n];n--;return 1;
    }
    int delmin(int& i,elem_t& e){
        if (n<1) return 0;i=ind[1];
        for (e=h[p=1],c=2;c<n&&_cp(h[c+=(c<n-1&&_cp(h[c+1],h[c]))],h[n]);h[map[ind[p]=ind[c]]=p]=h[c],p=c,c<<=1);
        h[map[ind[p]=ind[n]]=p]=h[n];n--;return 1;
    }
};
 
void dijkstra(int n,edge_t* list[],int s,elem_t* min,int* pre){
    heap h;
    edge_t* t;elem_t e;
    int v[MAXN],i;
    for (h.init(),i=0;i<n;i++)
        min[i]=((i==s)?0:inf),v[i]=0,pre[i]=-1,h.ins(i,min[i]);
    while (h.delmin(i,e))
        for (v[i]=1,t=list[i];t;t=t->next)
            if (!v[t->to]&&min[i]+t->len<min[t->to])
                pre[t->to]=i,h.del(t->to,e),min[t->to]=e=min[i]+t->len,h.ins(t->to,e);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值