在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
思路:
对车票进行枚举 , 先从起始点和终点跑一次最短路:dist[0] 和 dist[1] 。
在迪杰斯特拉中,使用mp[0] 和 mp[1] 分别记录从到这个点的上一个点是谁。
记录初始价值ans为dist[0][ed] ;(ed为终点,dist[0]为从起始点到别的点的距离;
遍历每张车票:
将花费分为三段:起点 ->车票a点 , 车票a点-> 车票b点 , 车票b点->终点;
若最小价值ans大于使用车票的价值,改变ans,记录zda和zdb为车票的a,b点。
ll zda = -1, zdb = -1;
for(int i = 1; i<= T ; i ++){
ll x , y , pr;
cin >> x >> y >> pr;
if(dist[0][x] + dist[1][y] + pr < ans){
ans = dist[0][x] + dist[1][y] + pr;
zda = x , zdb = y;
}
}
最后,如果使用了车票,起点到zda,从zdb到终点就是路径,否则就是从起点到终点的路径。
vector<int>v;
if(~zda){
ll x = zda , y = zdb;
while(x){
v.push_back(x);x = mp[0][x];
}
reverse(v.begin(),v.end());
while(y){
v.push_back(y);y = mp[1][y];
}
}else{
while(sta){
v.push_back(sta);ed = mp[1][sta];
}
}
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll int
ll n , m , T;
const int N = 505 , M = 1005;
int sta , ed;
int mp[2][N];
int e[M] , ne[M] , w[M] , dist[2][N] , st[N] , idx , h[N];
void add(int a ,int b, int c){
ne[idx] = h[a] , e[idx] = b , w[idx] = c , h[a] = idx ++;
}
#define pii pair<int,int>
void bfs(ll ty){
memset(st,0,sizeof st);
priority_queue<pii,vector<pii>,greater<pii> > q;
if(ty == 0)q.push({dist[0][sta],sta});
if(ty == 1)q.push({dist[1][ed],ed});
while(!q.empty()){
auto 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[ty][x] <= dist[ty][t] + w[i])continue;
dist[ty][x] = dist[ty][t] + w[i];
mp[ty][x] = t;
q.push({dist[ty][x],x});
}
}
}
int main(){
ll T = 0;
while(cin >> n >> sta >> ed){
if(T ++)cout << endl;
memset(dist,0x3f ,sizeof dist);
memset(h , -1 , sizeof h);
idx = 0;
cin >> m;
while(m --){
ll a , b , c;
cin >> a >> b >> c;
add(a,b,c) , add(b,a,c);
}
dist[0][sta] = dist[1][ed] = 0 ;
mp[0][sta] = mp[1][ed] = 0;
bfs(0) , bfs(1);
ll ans = dist[0][ed];
cin >> T;
ll zda = -1, zdb = -1;
for(int i = 1; i<= T ; i ++){
ll x , y , pr;
cin >> x >> y >> pr;
if(dist[0][x] + dist[1][y] + pr < ans){
ans = dist[0][x] + dist[1][y] + pr;
zda = x , zdb = y;
}
}
vector<int>v;
if(~zda){
ll x = zda , y = zdb;
while(x){
v.push_back(x);x = mp[0][x];
}
reverse(v.begin(),v.end());
while(y){
v.push_back(y);y = mp[1][y];
}
}else{
while(sta){
v.push_back(sta);ed = mp[1][sta];
}
}
for(int i = 0 ; i < v.size() ; i ++){
if(i)cout << " " ;cout << v[i];
}cout << endl;
if(~zda)cout << zda << endl;
else cout << "Ticket Not Used\n";
cout << ans << endl;
}
}