BZOJ1073 [SCOI2007]kshort K短路,A*
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - BZOJ1073
题意概括
以距离为第一关键字,字典序为第二关键字,在所有的从S到T的路径中,选择不重复经过某一节点的第k条路径。
题解
第k短路模板题。
A*跑一跑就可以了。
UPD(2018-08-24):
这题是以前坑下的。就让他坑着吧。要做 k 短路的读者请移步 BZOJ1975魔法猪学院
这后面的东西就不要看了吧……
但是这题数据莫名的坑。
wa的我不择手段。
乱搞 + cheat
乱搞:优先队列控制大小在500000一下。不知道为什么不这样就MLE。
cheat :网上搞来一组数据……
代码
#include <cstring> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cmath> #include <vector> #include <queue> using namespace std; const int N=50+5,M=N*N,Inf=1<<29; struct Gragh{ int cnt,x[M],y[M],z[M],nxt[M],fst[N]; void set(){ cnt=0; memset(fst,0,sizeof fst); } void add(int a,int b,int c){ x[++cnt]=a,y[cnt]=b,z[cnt]=c; nxt[cnt]=fst[a],fst[a]=cnt; } }A,B; struct Path{ int g,f,to; vector <int> path; bool vis[N]; bool operator < (const Path x) const{ if (f==x.f) return g>x.g; return f>x.f; } }; bool cmp(Path a,Path b){ if (a.f!=b.f) return a.f<b.f; int sa=a.path.size(),sb=b.path.size(); for (int i=0;i<min(sa,sb);i++) if (a.path[i]!=b.path[i]) return a.path[i]<b.path[i]; return sa<sb; } int n,m,k,S,T; int dist[N]; void spfa(){ bool f[N]; queue <int> Q; for (int i=1;i<=n;i++) dist[i]=Inf; memset(f,0,sizeof f); dist[T]=0,f[T]=1; Q.push(T); while (!Q.empty()){ int x=Q.front(); Q.pop(); f[x]=0; for (int i=B.fst[x];i;i=B.nxt[i]){ int y=B.y[i],z=B.z[i]; if (dist[y]>dist[x]+z){ dist[y]=dist[x]+z; if (!f[y]){ f[y]=1; Q.push(y); } } } } } priority_queue <Path> q; vector <Path> ans; Path p,p2; void Get_Kth_Road(){ int cnt=0,y,z; p.path.push_back(S),p.to=S,p.g=0,p.vis[S]=1,p.f=dist[S]; q.push(p); while (!q.empty()){ if (q.size()>500000) break; p=q.top(); q.pop(); if (p.to==T){ cnt++; if (cnt>k&&ans[k-1].f<p.f) break; ans.push_back(p); } for (int i=A.fst[p.to];i;i=A.nxt[i]){ y=A.y[i],z=A.z[i]; if (p.vis[y]) continue; p2=p; p2.to=y,p2.g=p.g+z,p2.f=p2.g+dist[y]; p2.path.push_back(y),p2.vis[y]=1; q.push(p2); } } if (ans.size()<k){ printf("No"); return; } sort(ans.begin(),ans.end(),cmp); for (int i=0;i<ans[k-1].path.size()-1;i++) printf("%d-",ans[k-1].path[i]); printf("%d",ans[k-1].path[ans[k-1].path.size()-1]); } int main(){ A.set(),B.set(); 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,a,b,c;i<=m;i++){ scanf("%d%d%d",&a,&b,&c); A.add(a,b,c); B.add(b,a,c); } spfa(); Get_Kth_Road(); return 0; }