PTA-旅游大巴(25分);

该文描述了一个关于在W市使用旅游大巴前往景点A的最短路径规划问题。通过输入的站点数、起始点和终点信息,以及普通线和快速线的路段数据,利用图的广度优先搜索算法(BFS)寻找最快路线。如果无需使用快速线车票,输出特殊提示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在W市中,旅游大巴是市民从市内去景区A的首选交通工具。旅游大巴分为普通线和快速线两种,线路、速度和价钱都不同。你有一张快速线车票,可以坐一站快速线,而其他时候只能乘坐普通线。假设换乘时间忽略不计,你的任务是找一条去景点A最快的线路。

输入包含多组数据。每组数据第一行为3个整数N,S和E(2≤N≤500,1≤S,E≤100),即旅游大巴中的停靠站总数,起点和终点(即景点A所在站)编号。下一行包含一个整数M(1≤M≤1000),即普通线的路段条数。以下M行每行3个整数X,Y,Z(1≤X,Y≤N,1≤Z≤100),表示可以乘坐普通线在站点X和站点Y之间往返,其中单程需要Z分钟。下一行为快速线的路段条数K(1≤K≤1000),以下K行是这些路段的描述,格式同普通线。所有路段都是双向的,但有可能必须使用快速车票才能到达景点A。保证最优解唯一。

对于每组数据,输出3行。第一行按访问顺序给出经过的各个站点(包括起点和终点),第二行是换乘快速线的车站编号(如果没有快速线车票,输出Ticket Not Used),第三行是总时间。

注意:输出时,每两组数据之间要加一个空行。并且不会过滤行末空格

输入样例:

4 1 4
4
1 2 2
1 3 3
2 4 4
3 4 5
1
2 4 3

输出样例:

1 2 4
2
5
#include<bits/stdc++.h>
using namespace std;
#define int long long
int head[10005*2];
int dist[10005*2];
int vis[10005*2],dis[10005*2];
int n,m,l,s,t,ans;
int p[1000];
int wa[1000];
struct node{
	int to,w,next;
}f[10005];
int cnt;
struct da{
	int x,y;
};
void add(int a,int b,int c){
	f[cnt].to=b;
	f[cnt].w=c;
	f[cnt].next=head[a];
	head[a]=cnt++;
}
struct cmp{
	bool operator()(da a,da b){
		return a.y>b.y;
	}
};
void bfs(int x){
	priority_queue<da,vector<da>,cmp>q;
	memset(dist,0x3f,sizeof(dist));
	memset(vis,0,sizeof(vis));
	memset(p,-1,sizeof(p));
	dist[x]=0;
	q.push({x,dist[x]});
	while(!q.empty()){
		da z=q.top();
		q.pop();
		if(vis[z.x])continue;
		vis[z.x]=0;
		for(int i=head[z.x];i!=-1;i=f[i].next){
			int g=f[i].to;
			if(dist[g]>dist[z.x]+f[i].w){
				dist[g]=dist[z.x]+f[i].w;
				q.push({g,dist[g]});
				p[g]=z.x;
			}
		}
	}
}
signed main(){
	int naa=0;
	//判段换行 
	while(cin>>n>>s>>t){
		cnt=0;
		if(naa){
			cout<<endl;
		}
		memset(head,-1,sizeof(head));
		memset(p,-1,sizeof(p));
		memset(dis,0x3f,sizeof(dis));
		cin>>m;
		while(m--){
			int a,b,c;
			cin>>a>>b>>c;
			add(a,b,c);
			add(b,a,c);
		}
		bfs(s);
		for(int i=1;i<=n;i++){
			dis[i]=dist[i];
			wa[i]=p[i];
		}
		bfs(t);
		//qx等于终点,qx=-1可以排除第三给样例点的打印路径问题 
		int qx=t,qy=-1;
		int k;
		cin>>k;
		ans=dist[s];
		while(k--){
			int a,b,c;
			cin>>a>>b>>c;
			if(dis[a]==0x3f3f3f3f3f3f3f3f||dist[b]==0x3f3f3f3f3f3f3f3f){
				continue;
			}
			if(dist[b]+dis[a]+c<ans){
				ans=dist[b]+dis[a]+c;
				qx=a;
				qy=b;
			}
		}
		vector<int>aps;
		int z=qx;
		while(z!=-1){
			aps.push_back(z);
			z=wa[z];
		}
		reverse(aps.begin(),aps.end());
		z=qy;
		while(z!=-1){
			aps.push_back(z);
			z=p[z];
		}
//		打印路径
		for(int i=0;i<aps.size();i++){
			if(i!=0)cout<<" ";
			cout<<aps[i];
		}
		cout<<endl;
		if(qx==t&&qy==-1){
			cout<<"Ticket Not Used"<<endl;
			cout<<ans<<endl;
		}else{
			cout<<qx<<endl;
			cout<<ans<<endl;
		}
		naa++;
	}
	return 0;
}

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值