PTA 去火车站

该程序设计题要求找到从学校到火车站的最快路线,考虑公交和轻轨的组合,并且利用学生证免费乘坐一站轻轨的优惠。通过迪杰斯特拉算法计算起点到所有点的最短路径,然后比较是否通过轻轨换乘能缩短总时间,找到最佳换乘策略。

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

寒假到了,小明准备坐火车回老家,现在他从学校出发去火车站,CC市去火车站有两种方式:轻轨和公交车。小明为了省钱,准备主要以乘坐公交为主。CC市还有一项优惠政策,持学生证可以免费乘坐一站轻轨(但只能乘坐一站)。小明想尽快到达火车站,请编写程序为小明找到一条从学校到火车站最快的路线及换乘轻轨的方案。

假设换乘时间忽略不计,公交车与轻轨站点相同,但线路和速度不一定相同,所有线路都是双向的。可以第一站就乘坐轻轨,也可以最后一站乘坐轻轨,也可以在中间某站坐轻轨。如果乘坐轻轨和不乘坐轻轨到达火车站的时间相同,则无需换乘轻轨。最多坐一站轻轨。

输入格式:

输入包含多组数据。每组数据第一行为3个整数n、s和t,分别表示车站数(编号为1至n),小明学校所在的站和火车站所在的站。下一行为一个整数m,表示公交车的线路信息,接下来m行,每行为3个正整数a、b、c,表示公交车从a站到b站需要c分钟。下一行为一个整数k,表示轻轨的线路信息,接下来k行,每行为3个正整数x、y、z,表示轻轨从x站到y站需要z分钟。所有整数均不超过20000。

输出格式:

对每组数据输出2行。第1行为1个整数T,表示从学校到达火车站的最短时间;第2行为一个整数K,表示在站点K换乘轻轨,若有多个可能的换乘点,则输出编号最小者,如果无需换乘轻轨,则第二行输出“no metro”。

输入样例:

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

输出样例:

5
2
5
2

思路:

使用迪杰斯特拉模板算出起点,终点到所有点的最短路;

根据所有的车票(a<->b)计算(起点->a+轻轨时间+b->终点)/(起点->b+轻轨时间+a->终点)

如果小于ans(初值为起点到终点的时间),就改变他,并且改变way(在哪个点转站);

最后如果way的值未改变就输出“no metro”;

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
ll n , T , k , idx , sta , en;
const int l = 40005;
int ne[l] , e[l] , w[l] , h[l] , dist[l];
int d1[l] , d2[l];
bool st[l];
void bfs(int x){
	memset(st,0,sizeof st);
	memset(dist,0x3f,sizeof dist);
	priority_queue<pii,vector<pii>,greater<pii> > q;
	dist[x] = 0;
	q.push({dist[x],x});
	while(!q.empty()){
		int t = q.top().second;
		q.pop();
		if(st[t])continue;
		st[t] = 1;
		for(int i = h[t] ; ~ i ; i = ne[i]){
			int x = e[i];
			if(dist[x] <= dist[t] + w[i])continue;
			dist[x] = dist[t] + w[i];
			q.push({dist[x],x});
		}
	}
}
void add(int a,int b,int c){
	ne[idx] = h[a];
	e[idx] = b;
	w[idx] = c;
	h[a] = idx ++;
}
int main(){
	while(cin >> n >> sta >> en){
			idx = 0;
		memset(h , - 1 , sizeof h);
		cin >> T;
		while(T --){
			int a , b , c;
			cin >> a >> b >> c;
			add(a,b,c);
			add(b,a,c);
		}
		cin >> T;
		bfs(sta);for(int i = 1 ; i <= n ; i ++)d1[i] = dist[i];
		bfs(en );for(int i = 1 ; i <= n ; i ++)d2[i] = dist[i];
		int ans = d1[en];
		int way = 0;
		while(T --){
			int a , b , c;
			cin >> a >> b >> c;
			if(d1[a] + c + d2[b] < ans){
				way = a;
				ans = d1[a] + c + d2[b];
			}
			if(d1[b] + c + d2[a] < ans){
				way = b;
				ans = d1[b] + c + d2[a] ;
			}
		}
		cout << ans << endl;
		way ? cout << way << endl : cout << "no metro" << endl;
	}
	

} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值