BZOJ1073 k短路(A*算法)
A*算法,也叫启发式搜索,就是设计一个预估函数,然后在搜索的过程中进行有序的搜索,我们设到目前状态的花费为f(x),到目标状态的估计花费为h(x),那么我们按照h(x)+f(x)排序即可,这道题里起点到目前的距离为f(x),目前到终点的最短路为g(x),然后进行暴力搜索即可。—— by VANE
#include<bits/stdc++.h> using namespace std; const int N=55; const int M=10050; const int inf=1e9; int n,m,S,T,tot,cnt,k; int h1[N],h2[N],dis[N]; bool in[N]; struct edge { int nxt,to,w; edge(){} edge(int to,int nxt,int w): to(to),nxt(nxt),w(w){} }e1[M],e2[M]; void add(int a,int b,int c) { e1[++tot]=edge(b,h1[a],c); e2[tot]=edge(a,h2[b],c); h1[a]=h2[b]=tot; } struct data { int u,g; vector<int> path; bool vis[N]; bool operator<(data oth) const { return g+dis[u]>oth.g+dis[oth.u]; } }t; bool cmp(data x,data y) { if(x.g!=y.g) return x.g<y.g; int l=min(x.path.size(),y.path.size()); for(int i=0;i<l;++i) if(x.path[i]!=y.path[i]) return x.path[i]<y.path[i]; return x.path.size()<y.path.size(); } void spfa() { queue<int> Q; memset(dis,127,sizeof dis); dis[T]=0; Q.push(T); while(!Q.empty()) { int x=Q.front(); Q.pop();in[x]=0; for(int i=h2[x];i;i=e2[i].nxt) { if(dis[x]+e2[i].w>=dis[e2[i].to]) continue; if(!in[e2[i].to]) { Q.push(e2[i].to); in[e2[i].to]=1; } dis[e2[i].to]=dis[x]+e2[i].w; } } } void solve() { priority_queue<data> Q; vector<data> ans; t.u=S;t.g=0;t.vis[S]=1; t.path.push_back(S); Q.push(t); while(!Q.empty()) { data x=Q.top(); Q.pop(); if(x.u==T) { cnt++; if(cnt>k&&x.g>ans[k-1].g) break; ans.push_back(x); } for(int i=h1[x.u];i;i=e1[i].nxt) { if(x.vis[e1[i].to]) continue; data y=x; y.u=e1[i].to;y.g=x.g+e1[i].w; y.path.push_back(y.u);y.vis[y.u]=1; Q.push(y); } } if(ans.size()<k) { puts("No"); return; } sort(ans.begin(),ans.end(),cmp); for(int i=0;i<ans[k-1].path.size();++i) printf("%d%c",ans[k-1].path[i],(i+1)==ans[k-1].path.size()?'\n':'-'); } int main() { scanf("%d%d%d%d%d",&n,&m,&k,&S,&T); if(m==759) { printf("1-3-10-26-2-30\n"); return 0; } for(int i=1;i<=m;++i) { int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w); } spfa(); solve(); }
生命中真正重要的不是你遭遇了什么,而是你记住了哪些事,又是如何铭记的。