迪杰斯特拉

算法重点是松弛操作,解释为用一个dis数组记录从起点走到当前点的最短距离,如果当前点的dis值加上走到相邻点的距离小于相邻点的dis值,则更新相邻点的dis为前面两数之和。之后不断维护dis的值直到终点。

实现方面可以用优先队列不断取出dis值小的点,到终点结束。

head提前全置为-1,无向图需要st和ts的顺序插入两遍

nnum:顶点数 egnum:边数

点标号从0开始

优先队列

const int INF = 0xfffffff;
struct Edge{
    int s, t, v, nxt;
}e[1000005];
int n, m, cnt, head[100005], dis[100005], vis[100005];
void add(int s, int t, int v){
    e[cnt].s = s; e[cnt].t = t; e[cnt].v = v; e[cnt].nxt = head[s]; head[s] = cnt++;
}
struct Heap{
    int s, d;
    friend bool operator <(Heap a, Heap b){
        return a.d > b.d;
    }
};
void INIT(){
    cnt = 0;
    memset(head, -1, sizeof(head)); 
} 
void Dijkstra(int s, int N){
    memset(vis, 0, sizeof(vis));
    for(int i = 1; i <= N; i++) 
        dis[i] = INF;
    dis[s] = 0;
    priority_queue <Heap> q;
    Heap start;
    start.s = s; start.d = dis[s];
    q.push(start);
    while(!q.empty()){
        Heap u = q.top();
        q.pop();
        if(vis[u.s]) continue;
        vis[u.s] = 1;
        for(int i = head[u.s]; i != -1; i = e[i].nxt){
            int t = e[i].t;
            if(!vis[t] && dis[t] > e[i].v + dis[u.s]){
                dis[t] = e[i].v + dis[u.s];
                Heap e;
                e.s = t; e.d = dis[t];
                q.push(e);
            }
        }
    } 
}
View Code

手写堆

const int INF=0xfffffff ;
const int egnum=200005 ;
const int nnum=1005 ;
struct node
{
    int s,t,v ;
    int nxt ;
} ;
node e[egnum] ;
int cnt,head[nnum] ;
void add(int s,int t,int v)
{
    e[cnt].s=s ;e[cnt].t=t ;e[cnt].v=v ;e[cnt].nxt=head[s] ;head[s]=cnt++ ;
}
int dis[nnum],vis[nnum] ;
struct heap
{
    int s,d ;
} ;
heap hp[nnum] ;
int heapsize ;
void up(int son)
{
    while(son!=1)
    {
        if(hp[son>>1].d>hp[son].d)
        {
            swap(hp[son>>1],hp[son]) ;
            son>>=1 ;
        }
        else
            break ;
    }
}
void down(int fa)
{
    int son=fa<<1 ;
    while(son<=heapsize)
    {
        if(son<heapsize && hp[son+1].d<hp[son].d)
            son++ ;
        if(hp[fa].d>hp[son].d)
        {
            swap(hp[fa],hp[son]) ;
            fa=son ;son<<=1 ;
        }
        else break ;
    }
}
void pop()
{
    swap(hp[1],hp[heapsize--]) ;
    down(1) ;
}
void push(heap x)
{
    hp[++heapsize]=x ;
    up(heapsize) ;
}
void Dijkstra(int s,int n)
{
    heapsize=0 ;
    memset(vis,0,sizeof(vis)) ;
    for(int i=1 ;i<=n ;i++)
    {
        if(i==s)
            dis[i]=0 ;
        else    
            dis[i]=INF ;
    }
    heap st ;
    st.s=s ;st.d=dis[s] ;
    push(st) ;
    while(heapsize)
    {
        heap u=hp[1] ;
        pop() ;
        if(vis[u.s])continue ;
        vis[u.s]=1 ;
        for(int i=head[u.s] ;i!=-1 ;i=e[i].nxt)
        {
            int tt=e[i].t ;
            if(!vis[tt] && dis[tt]>e[i].v+dis[u.s])
            {
                dis[tt]=e[i].v+dis[u.s] ;
                heap ttt ;
                ttt.s=tt ;ttt.d=dis[tt] ;
                push(ttt) ;
            }
        }
    } 
}
View Code