QQ联系我

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条简单路

题解

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;
}
posted @ 2017-10-31 20:11  czy020202  阅读(328)  评论(0编辑  收藏  举报