迪杰斯特拉
算法重点是松弛操作,解释为用一个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); } } } }
手写堆
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) ; } } } }