给出原点和终点,给出一个有向图,问起点到终点的第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; }