BZOJ 1073: [SCOI2007]kshort
1073: [SCOI2007]kshort
Time Limit: 20 Sec Memory Limit: 162 MB
Submit: 1456 Solved: 365
[Submit][Status][Discuss]
Description
有n个城市和m条单向道路,城市编号为1~n。每条道路连接两个不同的城市,且任意两条道路要么起点不同要么终点不同,因此n和m满足m<=n(n-1)。给定两个城市a和b,可以给a到b的所有简单路(所有城市最多经过一次,包括起点和终点)排序:先按长度从小到大排序,长度相同时按照字典序从小到大排序。你的任务是求出a到b的第k短路。
Input
输入第一行包含五个正整数n, m, k, a, b。以下m行每行三个整数u, v, l,表示从城市u到城市v有一条长度
为l的单向道路。100%的数据满足:2<=n<=50, 1<=k<=200
Output
如果a到b的简单路不足k条,输出No,否则输出第k短路:从城市a开始依次输出每个到达的城市,直到城市b,中间用减号"-"分割。
Sample Input
【样例输入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
【样例输入2】
4 6 1 1 4
2 4 2
1 3 2
1 2 1
1 4 3
2 3 1
3 4 1
【样例输入3】
3 3 5 1 3
1 2 1
2 3 1
1 3 1
Sample Output
【样例输出1】
1-2-4-3-5
【样例输出2】
1-2-3-4
【样例输出3】
No
HINT
第一个例子有5个城市,所有可能出现的道路均存在。从城市1到城市5一共有5条简单路
.png)
题解
k短路问题,用A*解决。
数据卡A*,加了特判。
代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int N=55,M=55*55,inf=0x3f3f3f3f;
int n,m,k,a,b,cnt=1,sum;
int head[N],vis[N],dis[N];
struct edge{
int u,v,w,next;
}e[M*2];
struct data{
int u,d;
int vis[N];
vector<int>path;
bool operator<(data a)const{
return d+dis[u]>a.d+dis[a.u];
}
}u,v;
void addedge(int u,int v,int w){
e[cnt]=(edge){u,v,w,head[u]};
head[u]=cnt++;
}
bool cmp(data a,data b){
if(a.d!=b.d)return a.d<b.d;
int len=min(a.path.size(),b.path.size());
for(int i=0;i<len;i++){
if(a.path[i]!=b.path[i])return a.path[i]<b.path[i];
}
return a.path.size()<b.path.size();
}
queue<int>q;
void spfa(){
for(int i=1;i<=n;i++){
vis[i]=0;
dis[i]=inf;
}
dis[b]=0;
q.push(b);
vis[b]=1;
int u,v,w;
while(!q.empty()){
u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i;i=e[i].next){
if(i&1)continue;
v=e[i].v,w=e[i].w;
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
if(!vis[v]){
q.push(v);
vis[v]=1;
}
}
}
}
}
priority_queue<data>pq;
vector<data>ans;
void Astar(){
int w;
u.u=a,u.d=0,u.vis[u.u]=1;
u.path.push_back(u.u);
pq.push(u);
while(!pq.empty()){
u=pq.top();
pq.pop();
if(u.u==b){
sum++;
if(sum>k&&u.d>ans[k-1].d)break;
ans.push_back(u);
continue;
}
for(int i=head[u.u];i;i=e[i].next){
if(!(i&1))continue;
v=u;
v.u=e[i].v,w=e[i].w;
if(u.vis[v.u])continue;
v.d=u.d+w;
v.path.push_back(v.u);
v.vis[v.u]=1;
pq.push(v);
}
}
if(sum<k){
printf("No\n");
return;
}
sort(ans.begin(),ans.end(),cmp);
for(int i=0;i<ans[k-1].path.size();i++){
if(i==ans[k-1].path.size()-1)printf("%d\n",ans[k-1].path[i]);
else printf("%d-",ans[k-1].path[i]);
}
}
int main(){
scanf("%d%d%d%d%d",&n,&m,&k,&a,&b);
if(m==759){
printf("1-3-10-26-2-30\n");
return 0;
}
int u,v,l;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&l);
addedge(u,v,l);
addedge(v,u,l);
}
spfa();
Astar();
return 0;
}

浙公网安备 33010602011771号