[模板] k短路

简介

Dijkstra最短路+A*搜索.

先逆向求所有点到终点的最短路 (dis[i]).

定义估价函数 (f[i] = d[i] + dis[i]) , 其中 (d[i]) 表示当前起点到 (i) 点的路径长度, 则 (f[i]) 表示一条从 (u)(v) 经过 (i) 点的路径长度.

与Dijkstra算法类似, 将 (f[i]) 放到堆中, 每次求出 (f[i]) 最小的节点 (u) , 维护相邻节点 (v) :

[d[v] = d[u] + val(u,v) ]

[ f[v] = f[u] - dis[u] + dis[v] + val(u,v) $$. 当第 $k$ 次 $u$ 为终点, $f[u]$ 即为起点到终点的第 $k$ 短路. ### 代码 ``` //the nth point is departure, 1st is destination const int nsz=1050,msz=10050; const ll ninf=1e16; int n,m,k; struct te{int t,pr,v;}edge[msz*2]; int hd[nsz],pe=1; void adde(int f,int t,int v){edge[++pe]=(te){t,hd[f],v};hd[f]=pe;} void addsg(int f,int t,int v){adde(f,t,v);adde(t,f,-1);} ll dis[nsz],vi[nsz]; struct tnd{ll p,d;}; bool operator<(tnd l,tnd r){return l.d>r.d;} priority_queue<tnd> pq; void dij(int f){ rep(i,1,n)dis[i]=ninf; dis[f]=0; pq.push((tnd){f,0}); while(!pq.empty()){ int u=pq.top().p;pq.pop(); if(vi[u])continue; for(int i=hd[u],v=edge[i].t;i;i=edge[i].pr,v=edge[i].t){ if(edge[i].v!=-1)continue;//inv edge if(dis[v]>dis[u]+edge[i^1].v)dis[v]=dis[u]+edge[i^1].v,pq.push((tnd){v,dis[v]}); } } // rep(i,1,n)cout<<dis[i]<<' '; } ll ans[nsz],pa=0; void astar(){ if(dis[n]>=ninf)return; pq.push((tnd){n,dis[n]}); while(!pq.empty()){ ll u=pq.top().p,d=pq.top().d;pq.pop(); if(u==1){ ans[++pa]=d; if(pa==k)break; continue; } for(int i=hd[u],v=edge[i].t;i;i=edge[i].pr,v=edge[i].t){ if(edge[i].v==-1)continue; pq.push((tnd){v,d-dis[u]+dis[v]+edge[i].v}); } } } //use dij(1); while(!pq.empty())pq.pop(); astar(); ```]

原文地址:https://www.cnblogs.com/ubospica/p/9879307.html