簡介
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]<<'\n'; } 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(); ```\]
