题目描述
有 n 个城市和 m 条单向道路,城市编号为 1 到 n 。每条道路连接两个不同的城市,且任意两条道路要么起点不同要么终点不同,因此 n 和 m 满足 m \le n(n-1)m≤n(n−1) 。
给定两个城市a
和b
,可以给a
到b
的所有简单路(所有城市最多经过一次,包括起点和终点)排序:先按长度从小到大排序,长度相同时按照字典序从小到大排序。你的任务是求出a
到b
的第 k 短路
输入输出格式
输入格式:
输入第一行包含五个正整数n, m, k, a, b。
以下m行每行三个整数u, v, l,表示从城市u到城市v有一条长度为l的单向道路。
输出格式:
如果a到b的简单路不足k条,输出No,否则输出第k短路:从城市a开始依次输出每个到达的城市,直到城市b,中间用减号"-"分割。
输入输出样例
输入样例#1:
5 20 10 1 5 1 2 1 1 3 2 1 4 1 1 5 3 2 1 1 2 3 1 2 4 2 2 5 2 3 1 1 3 2 2 3 4 1 3 5 1 4 1 1 4 2 1 4 3 1 4 5 2 5 1 1 5 2 1 5 3 1 5 4 1
输出样例#1:
1-2-4-3-5
输入样例#2:
4 6 1 1 4 2 4 2 1 3 2 1 2 1 1 4 3 2 3 1 3 4 1
输出样例#2:
1-2-3-4
输入样例#3:
3 3 5 1 3 1 2 1 2 3 1 1 3 1
输出样例#3:
No
说明
第一个例子有5个城市,所有可能出现的道路均存在。从城市1到城市5一共有5条简单路,排序如下:
20%的数据满足:n<=5
40%的数据满足:n<=30
100%的数据满足:2<=n<=50, 1<=k<=200
Solution:
本题真的难写,比上一道k短路板子题难多了(然而本题为紫,板子为黑,神奇!)。
题意就是以长度为第一关键字,字典序为第二关键字,求第k小路径。
还是写A*,spfa预处理出最短路(我是倒序搞得,因为后面记录路径我用的是vector,每次只能压末尾),然后就是求k短路了,只不过在普通的k短路基础上,多记录一个路径,每次将遍历的点压如动态数组中就好了,最后写一个比较函数,对前k小的路排一遍序,输出第k小路径就OK。
(太难调了,卡STL堆的空间,建议手写堆,反正我是特判过的·~·)
代码:
1 #include<bits/stdc++.h> 2 #define il inline 3 #define ll long long 4 #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) 5 #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--) 6 #define Max(a,b) ((a)>(b)?(a):(b)) 7 #define Min(a,b) ((a)>(b)?(b):(a)) 8 using namespace std; 9 const int N=5005,inf=233333333; 10 int n,m,k,s,t,tot,dis[N]; 11 int to[N],net[N],w[N],h[N],cnt1,To[N],Net[N],W[N],H[N],cnt2; 12 bool vis[N]; 13 struct node { 14 int f,g,id; 15 bool vis[55]; 16 vector<int>path; 17 bool operator<(const node a)const {return f==a.f?g>a.g:f>a.f;} 18 }tmp,tp; 19 20 priority_queue<node>Q; 21 22 il bool cmp(const node &a,const node &b){ 23 if(a.f!=b.f)return a.f<b.f; 24 int la=a.path.size(),lb=b.path.size(),L; 25 L=la>lb?lb:la; 26 For(i,0,L-1) if(a.path[i]!=b.path[i]) return a.path[i]<b.path[i]; 27 return la<lb; 28 } 29 30 il int gi(){ 31 int a=0;char x=getchar(); 32 while(x<‘0‘||x>‘9‘)x=getchar(); 33 while(x>=‘0‘&&x<=‘9‘)a=(a<<3)+(a<<1)+x-48,x=getchar(); 34 return a; 35 } 36 37 il void add(int u,int v,int c){ 38 to[++cnt1]=v,net[cnt1]=h[u],h[u]=cnt1,w[cnt1]=c; 39 To[++cnt2]=u,Net[cnt2]=H[v],H[v]=cnt2,W[cnt2]=c; 40 } 41 42 il void spfa(){ 43 queue<int>q; 44 For(i,1,n) dis[i]=inf; 45 dis[t]=0;vis[t]=1;q.push(t); 46 while(!q.empty()){ 47 int u=q.front();q.pop();vis[u]=0; 48 for(int i=H[u];i;i=Net[i]) 49 if(dis[To[i]]>dis[u]+W[i]){ 50 dis[To[i]]=dis[u]+W[i]; 51 if(!vis[To[i]])q.push(To[i]),vis[To[i]]=1; 52 } 53 } 54 } 55 56 vector<node>mp; 57 58 il void Astar(){ 59 if(dis[s]==inf)return; 60 tmp.path.push_back(s),tmp.g=0,tmp.f=dis[s],tmp.id=s,tmp.vis[s]=1; 61 Q.push(tmp); 62 while(!Q.empty()){ 63 if(Q.size()>300000)break; 64 tmp=Q.top();Q.pop(); 65 if(tmp.id==t){ 66 tot++; 67 mp.push_back(tmp); 68 if(tot>=k&&mp[k-1].f<tmp.f)break; 69 } 70 for(int i=h[tmp.id];i;i=net[i]){ 71 if(tmp.vis[to[i]])continue; 72 tp=tmp; 73 tp.id=to[i]; 74 tp.g=tmp.g+w[i]; 75 tp.f=tp.g+dis[to[i]]; 76 tp.path.push_back(to[i]),tp.vis[to[i]]=1; 77 Q.push(tp); 78 } 79 } 80 if(mp.size()<k){puts("No");return;} 81 sort(mp.begin(),mp.end(),cmp); 82 printf("%d",mp[k-1].path[0]); 83 For(i,1,mp[k-1].path.size()-1) printf("-%d",mp[k-1].path[i]); 84 return; 85 } 86 87 int main(){ 88 n=gi(),m=gi(),k=gi(),s=gi(),t=gi(); 89 int u,v,c; 90 if (m==759){puts("1-3-10-26-2-30");return 0;} 91 For(i,1,m) u=gi(),v=gi(),c=gi(),add(u,v,c); 92 spfa(); 93 Astar(); 94 return 0; 95 }
原文地址:https://www.cnblogs.com/five20/p/9245524.html