给出原点和终点,给出一个有向图,问起点到终点的第k短的路有多长。
首先确定这是一道搜索的题目,然而Gemini说这是一道A*,既然是A*那么就有估计值和实际值,估计值不好在搜索的时候计算,那么就先把距离预处理出来,就从终点到起点Dijsktra,最后再从起点A*,当终点进入优先队列k次时,那么所走的路径一定是第k短路。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
const int inf = (1<<31)-1;
const int maxn = 1010;
const int maxm = 100010;
#define clr(a,b) memset(a,b,sizeof(a))
int n,m;
int u,v,w,s,t,k;
int dis[maxn],done[maxn],cnt[maxn];
struct Edge{
int u,v,w;
Edge *nxt;
}meo[2*maxm],*head[maxn],*cur,*rehead[maxn];
struct node{
int dis,u;
bool operator < (const node &rhs)const{
return dis>rhs.dis;
}
};
struct star{
int d,u;
bool operator < (const star &rhs)const{
return d+dis[u]>rhs.d+dis[rhs.u];//*****
}
};
void adde(int u,int v,int w,Edge *f[]){
cur->v = v;
cur->w = w;
cur->nxt = f[u];
f[u] = cur++;
// printf("!%d %d %d\n",u,v,w);
}
void dijkstra(int s){
priority_queue<node>q;
for(int i = 1;i <= n;++i)dis[i] = inf;
dis[s] = 0;
q.push((node){dis[s],s});
while(!q.empty()){
node p = q.top();
q.pop();
int u = p.u;
if(done[u])continue;
done[u] = true;
for(Edge *it = rehead[u];it;it = it->nxt){
int v = it->v;
if(dis[v] > dis[u]+it->w){
dis[v] = dis[u] + it->w;
q.push((node){dis[v],v});
}
}
}
// for(int i = 1;i <= n;++i)printf("%d ",dis[i]);puts("");
}
int AStar(int s,int t){
if(dis[s] == inf)return -1;
if(s == t)++k;//*****
priority_queue <star> q;
q.push((star){0,s});
while(!q.empty()){
star p = q.top();
q.pop();
cnt[p.u]++;
if(cnt[t] == k)return p.d;
for(Edge *it = head[p.u];it;it = it->nxt){
q.push((star){it->w+p.d,it->v});
}
}
return -1;
}
int main(){
cur = meo;
scanf("%d%d",&n,&m);
for(int i = 1;i <= m;++i){
scanf("%d%d%d",&u,&v,&w);
adde(u,v,w,head);
adde(v,u,w,rehead);
}
scanf("%d%d%d",&s,&t,&k);
dijkstra(t);
printf("%d\n",AStar(s,t));
return 0;
}