TT 的旅行日记
众所周知,TT 有一只魔法猫。
今天他在 B 站上开启了一次旅行直播,记录他与魔法猫在喵星旅游时的奇遇。 TT 从家里出发,准备乘坐猫猫快线前往喵星机场。猫猫快线分为经济线和商业线两种,它们的速度与价钱都不同。当然啦,商业线要比经济线贵,TT 平常只能坐经济线,但是今天 TT 的魔法猫变出了一张商业线车票,可以坐一站商业线。假设 TT 换乘的时间忽略不计,请你帮 TT 找到一条去喵星机场最快的线路,不然就要误机了!
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 前往喵星机场花费的总时间。
**本题不忽略多余的空格和制表符,且每一组答案间要输出一个换行**
Sample Input
4 1 4
4
1 2 2
1 3 3
2 4 4
3 4 5
1
2 4 3
Sample Output
1 2 4
2
5
我的思路:
这道题的题意是,要从一个车站X到另一个车站Y,过程中要走经济线(或者经济线+一条商业线),找到最短的路径。这里的想法可以是利用求最短路的算法,外加一个记录前驱节点的数组pre,来记录路径。对于商业线的选择上,可以对于每条商业线a->b,找到起点和终点分别到a和b的距离,取拼接最小值+商业线a->b的权重w,即为经过当前商业线的最短路径。利用这样的思想,在实际操作中,只要进行两边求最短路的操作(从起点开始/从终点开始),记录两个距离数组,然后对于每条商业线遍历计算距离,最后再和不走商业线做一个对比就可以了。
我的总结:
最短路算法包括Dijkstra、Bellman_ford,SPFA,都应该灵活运用,并且不要搞混。
我的代码:
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const long long inf = 5*1e8;
struct Edg
{
long long to,next,w;
}edg[20001];
bool fl=false;
long long dis[10001][2],pre[10001][2],inq[10001][2],n,nn,sta,s,e,m,x0,y0,w0,head[1001],ind,kn,min_dis,ans1,ans2;
priority_queue<pair<int,int> > que;
void add(long long x,long long y,long long wei)
{
edg[ind].to=y;
edg[ind].next=head[x];
edg[ind].w=wei;
head[x]=ind;
ind++;
}
void print0(long long xx)
{
if(xx==s) {
printf("%d",s);
return;}
print0(pre[xx][0] );
printf(" %d",xx);
}
void print1(long long xx)
{
while(xx!=e)
{
printf("%d ",xx);
xx=pre[xx][1];
}
printf("%d\n",xx);
}
void init()
{
for(long long i=1;i<n+1;i++)
{
dis[i][0]=inf;
dis[i][1]=inf;
pre[i][0]=0;
pre[i][1]=0;
inq[i][0]=0;
inq[i][1]=0;
head[i]=0;
}
}
void Bell(long long jug)
{
if(jug==s) kn=0,sta=s;
else kn=1,sta=e;
dis[sta][kn]=0;
que.push(make_pair(0,sta));
while(!que.empty())
{
long long o=que.top().second;
que.pop();
if(inq[o][kn]) continue;
inq[o][kn]=1;
for(long long i=head[o];i;i=edg[i].next)
{
if(dis[edg[i].to][kn]>dis[o][kn]+edg[i].w){
dis[edg[i].to][kn]=dis[o][kn]+edg[i].w;
pre[edg[i].to][kn]=o;
que.push(make_pair(-dis[edg[i].to][kn],edg[i].to));
}
}
}
}
int main()
{
while(scanf("%d%d%d%d",&n,&s,&e,&m)!=EOF)
{
ind=1;
init();
for(long long i=0;i<m;i++)
{
scanf("%d%d%d",&x0,&y0,&w0);
add(x0,y0,w0);
add(y0,x0,w0);
}
Bell(s);
Bell(e);
scanf("%d",&nn);
min_dis=inf;
ans1=ans2=0;
for(long long i=0;i<nn;i++)
{
scanf("%d%d%d",&x0,&y0,&w0);
if(min(dis[x0][0]+dis[y0][1]+w0,dis[y0][0]+dis[x0][1]+w0) < min_dis)
{
min_dis=min(dis[x0][0]+dis[y0][1]+w0,dis[y0][0]+dis[x0][1]+w0);
if(dis[x0][0]+dis[y0][1]+w0 < dis[y0][0]+dis[x0][1]+w0) ans1=x0,ans2=y0;
else ans1=y0,ans2=x0;}
}
if(min_dis > dis[e][0]) min_dis=dis[e][0],ans1=0;
if(fl) printf("\n");
else fl=true;
if(ans1)
{//printf("**1**");
print0(ans1);
printf(" ");
print1(ans2);
printf("%d\n%d\n",ans1,min_dis);
}
else
{//printf("**2**");
print0(e);
printf("\nTicket Not Used\n%d\n",min_dis);
}
}
return 0;
}