题意
众所周知,TT 有一只魔法猫。
今天他在 B 站上开启了一次旅行直播,记录他与魔法猫在喵星旅游时的奇遇。 TT 从家里出发,准备乘坐猫猫快线前往喵星机场。猫猫快线分为经济线和商业线两种,它们的速度与价钱都不同。当然啦,商业线要比经济线贵,TT 平常只能坐经济线,但是今天 TT 的魔法猫变出了一张商业线车票,可以坐一站商业线。假设 TT 换乘的时间忽略不计,请你帮 TT 找到一条去喵星机场最快的线路,不然就要误机了!
输入
输入包含多组数据。每组数据第一行为 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 行是商业线路段的描述,格式同经济线。
所有路段都是双向的,但有可能必须使用商业车票才能到达机场。保证最优解唯一
输出
对于每组数据,输出3行。第一行按访问顺序给出 TT 经过的各个车站(包括起点和终点),第二行是 TT 换乘商业线的车站编号(如果没有使用商业线车票,输出"Ticket Not Used",不含引号),第三行是 TT 前往喵星机场花费的总时间。
本题不忽略多余的空格和制表符,且每一组答案间要输出一个换行
思路
该题显然是需要求一条最短路(时间最短),因为没有负边,所以可以用dij,但是这里不同的是路线中可以用一条商业线,因为商业线数固定,所以可以枚举每一条商业线(u,v),计算起点到u的最短路+v到终点的最短路+该商业线花费的时间,即以起点为源点求最短路,得到dis1数组,以终点为源点求最短路,得到dis2数组,又因为线路是双向的,所以枚举商业线(u,v,w),取min{dis1[u]+dis2[v]+w,dis1[v]+dis2[u]+w},最终在与不走商业线的答案取min.
总结
该题是典型的dij求最短路,区别在于有一条商业线,进行枚举就可用dij
反思
该题需要注意输出格式
代码
//dij堆优化 邻接表
//不能解决权值为负问题
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<vector>
using namespace std;
# define inf 100000000
int dis1[510],dis2[510];bool flag[510];int np1[510],np2[510];
int n,s,e;
priority_queue<pair<int,int> >q;//距离 点
vector<pair<int,int> >ve[510];// 点 权重
void dijkstra(int s,int dis[510],int np[510])
{
while(q.size()) q.pop();
memset(flag,0,sizeof(flag));
for(int i=1;i<=n;i++)
np[i]=s;
for(int i=1;i<=n;i++) dis[i]=inf;//最长路-inf
dis[s]=0;np[s]=-1;q.push(make_pair(0,s));
while(q.size())
{
int x=q.top().second;//int v=q.top().frist //最长路加的 //最长路也不能解决正环(循环)问题
q.pop();
if(flag[x])continue;//说明每个点dis[i]选出后就不会确定了,没有负权情况,更没有负环情况
//最长路这里需要改变 if(v<dis[x])continue;
flag[x]=1;//最长路这里就不要了
for(int i=0;i<ve[x].size();i++)
{
if(dis[ve[x][i].first]>dis[x]+ve[x][i].second)//最长路<
dis[ve[x][i].first]=dis[x]+ve[x][i].second,np[ve[x][i].first]=x,
q.push(make_pair(-dis[ve[x][i].first],ve[x][i].first));//最长路改成最大堆
}
}
}
void print(int s)
{
if(np1[s]==-1)
{cout<<s;return;
}
print(np1[s]);
cout<<" "<<s;
}
void pprint(int s)
{ if(s==e) cout<<s;
else cout<<s<<" ";
if(s==e)
return;
pprint(np2[s]);
}
int main()
{ int kkk=0;//freopen("in.txt","r",stdin);
while(scanf("%d%d%d",&n,&s,&e)!=EOF)
{ if(kkk!=0)cout<<endl;kkk++;
for(int i=1;i<=n;i++)
{
while(ve[i].size()) ve[i].pop_back();
}
int m;scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int a,b,c;scanf("%d%d%d",&a,&b,&c);
ve[a].push_back(make_pair(b,c));
ve[b].push_back(make_pair(a,c));
} dijkstra(s,dis1,np1);dijkstra(e,dis2,np2);//dis1[e]就是没有商业的
//dis1[u] dis1[v] //dis2[v] dis2[u]
int k;scanf("%d",&k);int x=s,y=e,t=dis1[e];bool flag=0;
for(int i=1;i<=k;i++)
{
int a,b,c;scanf("%d%d%d",&a,&b,&c);
int val=min(dis1[a]+dis2[b]+c,dis1[b]+dis2[a]+c);
if(t>val)
{ if(dis1[a]+dis2[b]+c>dis1[b]+dis2[a]+c)
t=val,x=b,y=a;
else t=val,x=a,y=b;flag=1;
}
}
if(!flag)
{
print(e);cout<<endl;cout<<"Ticket Not Used"<<endl;cout<<t<<endl;
}
else
{
print(x);cout<<" ";pprint(y);cout<<endl;cout<<x<<endl;cout<<t<<endl;
}
}
}