程序设计Week7——B-TT的旅行日记

博客介绍了如何解决一个包含经济线和商业线的最短路径问题,通过dijkstra算法寻找从起点到终点的最优路径。在存在商业线的情况下,需要判断是否使用商业线以达到最短时间。文章详细阐述了解题思路,包括如何记录最短路长和路径点,以及如何选择最佳商业线。最后,提供了实现代码并进行了总结。
摘要由CSDN通过智能技术生成

题目描述

从起点乘车到机场,路线有经济路线和商业路线,仅有一张商业线票,仅能坐一站的商业线,求最快路线。

Input

输入包含多组数据。每组数据第一行为 3 个整数 N, S 和 E (2 ≤ N ≤ 500, 1 ≤ S, E ≤ 100),即猫猫快线中的车站总数,起点和终点(即喵星机场所在站)编号。
下一行包含一个整数 M (1 ≤ M ≤ 1000),即经济线的路段条数。
接下来有 M 行,每行 3 个整数 X, Y, Z (1 ≤ X, Y ≤ N, 1 ≤ Z ≤ 100),表示 TT 可以乘坐经济线在车站 X 和车站 Y 之间往返,其中单程需要 Z 分钟。
下一行为商业线的路段条数 K (1 ≤ K ≤ 1000)。
接下来 K 行是商业线路段的描述,格式同经济线。
所有路段都是双向的,但有可能必须使用商业车票才能到达机场。保证最优解唯一。

Output

对于每组数据,输出3行。第一行按访问顺序给出 TT 经过的各个车站(包括起点和终点),第二行是 TT 换乘商业线的车站编号(如果没有使用商业线车票,输出"Ticket Not Used",不含引号),第三行是 TT 前往喵星机场花费的总时间。
本题不忽略多余的空格和制表符,且每一组答案间要输出一个换行

解题思路

首先,这肯定是一道单源最短路问题,边权就是时间,但问题在于它有两套路线:经济线与商业线,要求商业线最多选择一条,且保证了最优解唯一,直观的想法就是到底选不选一条商业线,根据这个选择来求解;
如果不选择,那说明通过经济线一定可以到达终点,那直接一次单源最短路就能求解,但如果仅通过经济线无法到达重点,则说明一定要选一条商业线,选择哪一条商业线才能使得整条路径最短?不妨每一条商业线都选一次,每次都比对一下,如果选择了这条商业线可以使得总路径最短,那我们就选择这条商业线,这个想法很自然。基于此,将整个程序的流程分为以下过程:

  • 输入经济线路径,根据经济线分别以起点和终点跑两次dijkstra,就可以记录起点到任一点i的最短路长和i到重点的最短路长,同时记录路径点;
  • 令ans=dis1[终点],记录当前只选择经济线的情况下的最短路长(不连通就是maxn);
  • 输入商业路线,对每一条商业路线进行选择,判断是否进行路径的更新,设该条商业线的起始点分别为u、v,边权为w,若选择这条商业线,则最总路长就会变为dis1[u]+dis2[v]+w(dis1[v]+dis2[u]+w,因为交通路线是无向的),通过比较对ans的大小进行更新,若选择该条商业线,则记录(或更新)这条商业线的起始点(因为只能选一条商业线);
  • 判断ans是否有变化来知道是否选择了商业线,再根据情况来输出路径的点,输出时要注意不同位置的点的输出顺序。

实现代码

#include<iostream>
#include<vector>
#include<queue>
using namespace std;

const int maxn=1e7;

struct edge
{
	int next,time;
};
vector<edge> G[1010];
int N,S,E,M,K,ans=0,busp=0,buss,buse;
int dis1[510]={maxn},dis2[510]={maxn},path1[510],path2[510];
bool vis[510];
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q;


void dijkstra(int s,int* ans,int* path)
{
	while(!q.empty())
		q.pop();
	q.push(make_pair(0,s));
	ans[s]=0;
	while(!q.empty())
	{
		int u=q.top().second;
		q.pop();
		if(vis[u]==false)
		{
			vis[u]=true;
			for(int i=0;i<G[u].size();++i)
			{
				int v=G[u][i].next,w=G[u][i].time;
				if(ans[v]>ans[u]+w)
				{
					ans[v]=ans[u]+w;
					path[v]=u;
					q.push(make_pair(ans[v],v));
				}
			}
		}
	}
}

void path_output1(int p)
{//递归倒序输出路径 :从S到p 
	if(path1[p]==0)
		cout<<p;
	else
	{ 
		path_output1(path1[p]);
		cout<<" "<<p;
	}
}

void path_output2(int p)
{//顺序输出路径 :从p到E 
	if(path2[p]==0)
		cout<<" "<<p;
	else
	{
		cout<<" "<<p;
		path_output2(path2[p]);
	}
}

void clear()
{
	for(int i=1;i<=N;++i)
	{
		dis1[i]=maxn;
		dis2[i]=maxn;
		path1[i]=0;
		path2[i]=0;
		vis[i]=false;
		ans=0;
		G[i].clear();
	}
}

int main()
{
	bool f=false;
	while(cin>>N>>S>>E)
	{
		if(f)
			cout<<endl;
		cin>>M;
		clear();
		for(int i=0;i<M;++i)
		{
			int u,v,w;
			cin>>u>>v>>w;
			edge x,y;
			x.next=v;
			x.time=w;
			y.next=u;
			y.time=w;
			G[u].push_back(x);
			G[v].push_back(y);
		}
		dijkstra(S,dis1,path1);
		for(int i=1;i<=N;++i)
			vis[i]=false;
		dijkstra(E,dis2,path2);
		ans=dis1[E];
		cin>>K;
		for(int i=0;i<K;++i)
		{
			int u,v,w;
			cin>>u>>v>>w;
			if(ans>dis1[u]+w+dis2[v])
			{
				ans=dis1[u]+w+dis2[v];
				buss=u;
				buse=v;
			}
			else if(ans>dis1[v]+dis2[u]+w)
			{
				ans=dis1[v]+dis2[u]+w;
				buss=v;
				buse=u;
			}
		}
		if(dis1[E]<=ans)
		{//不走商业线,从S经济线直达E 
			path_output1(E);
			cout<<endl<<"Ticket Not Used"<<endl;
			cout<<dis1[E]<<endl;
		}
		else
		{//必须走商业线 
		 	path_output1(buss);
		 	path_output2(buse);
		 	cout<<endl<<buss<<endl;
		 	cout<<ans<<endl;
		}
		f=true;
	}
	return 0;
} 

总结

这是一道单源最短路的变形题,难点在于如何选择一条商业线,这里使用的办法是,对每一条商业线都进行尝试,比较最短路长是否有变化进行选择,若选择了就设置“断点”,遍历结束后就得到了最短路长,再根据断点的位置来进行点的输出,而设置断点的前提是从起点和终点分别跑两次迪杰斯特拉算法,记录相关信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值