题目描述:
在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
题目思路:
一.跑2k遍最短路,去遍历每条快速线的费用,取最小
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e4+5;
const int inf=0x3f3f3f3f3f3f3f3f;
struct node{
int fr,v,next,top;
int val;
}arr[N];
int cnt,n,s,e;
int head[N],vis[N],dis[N];
int mix[505][505];
unordered_map<int,int>mp[N];
void add(int u,int v,int val){
arr[++cnt]={u,v,head[u],0,val};
arr[head[u]].top=cnt;
head[u]=cnt;
}
void dee(int now){
int up=arr[now].top;
int down=arr[now].next;
if(up==0)head[arr[now].fr]=down;
else arr[up].next=down;
if(down>0)arr[down].top=up;
}
int ans[N];
void inti(){
cnt=0;
memset(head,-1,sizeof head);
memset(mix,0x3f,sizeof mix);
for(int i=0;i<=n;i++){
mp[i].clear();
}
}
void dijkstra(int x){
memset(vis,0,sizeof vis);
memset(dis,0x3f,sizeof dis);
memset(ans,0,sizeof ans);
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
q.push({0,x});
dis[x]=0;
while(!q.empty()){
pair<int,int>index=q.top();
q.pop();
if(vis[index.second])continue;
vis[index.second]=1;
for(int i=head[index.second];~i;i=arr[i].next){
int v=arr[i].v;
if(dis[v]>index.first+arr[i].val){
dis[v]=index.first+arr[i].val;
ans[v]=index.second;
q.push({dis[v],v});
}
}
}
}
void solve(){
int f=0;
while(cin>>n>>s>>e){
if(f)cout<<endl;
f=1;
inti();
int m;cin>>m;
while(m--){
int a,b,c;cin>>a>>b>>c;
mix[a][b]=min(mix[a][b],c);
mix[b][a]=min(mix[b][a],c);
add(a,b,c);
add(b,a,c);
}
int fk;cin>>fk;
int minn=inf;
vector<int>last;
int ck=-1;
while(fk--){
int F=0;
int a,b,c;cin>>a>>b>>c;
if(mix[a][b]>c){
add(a,b,c);
add(b,a,c);
dijkstra(s);
dee(cnt);
dee(cnt-1);
}else{
F=1;
dijkstra(s);
}
if(dis[e]<minn){
int p=e;
last.clear();
last.push_back(p);
while(ans[p]!=0){
last.push_back(ans[p]);
p=ans[p];
}
minn=dis[e];
if(F==0){
mp[fk][a]++;
mp[fk][b]++;
}
ck=fk;
}
}
int ls=-1;
for(int i=last.size()-1;i>=0;i--){
if(i-1>=0&&mp[ck].count(last[i])&&mp[ck].count(last[i-1])){
ls=last[i];
}
cout<<last[i]<<(i==0?"\n":" ");
}
if(ls!=-1){
cout<<ls<<endl;
}else cout<<"Ticket Not Used"<<endl;
cout<<minn<<endl;
}
}
signed main(){
// IOS;
solve();
return 0;
}
二.跑两遍最短路。
去比较每条快速线被使用的费用是否会比不用快速线的费用要短。
不用快速线的费用为起点---->终点的费用。
用快速线的费用则为起点------>快速线起点的费用加上快速线的费用加上快速线------>终点的费用。
两者费用进行比较,短了则更新需要打印的路径。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int inf=0x3f3f3f3f3f3f3f3f;
const int N=1e5+5;
int n,s,e,cnt,m;
int vis[N],head[N],d[N],d1[N],d2[N];
int ans1[N],ans2[N];
vector<int>v,sumlc;
struct node{
int v,w,next;
}bian[N];
struct cmp{
bool operator()(int x,int y){
return d[x]>d[y];
}
};
void init(){
memset(head,-1,sizeof head);
memset(ans1,0,sizeof ans1);
memset(ans2,0,sizeof ans2);
cnt=1;
}
void add(int u,int v,int w){
bian[cnt].v=v;
bian[cnt].w=w;
bian[cnt].next=head[u];
head[u]=cnt++;
}
void djst(int x){
memset(d,0x3f,sizeof d);
memset(vis,0,sizeof vis);
priority_queue<int,vector<int>,cmp>q;
q.push(x);
d[x]=0;
while(!q.empty()){
int k=q.top();
q.pop();
if(vis[k])continue;
vis[k]=1;
for(int i=head[k];i!=-1;i=bian[i].next){
int v=bian[i].v;
int w=bian[i].w;
if(d[v]>d[k]+w){
d[v]=d[k]+w;
ans1[v]=k;
q.push(v);
}
}
}
}
void djst1(int x){
memset(d,0x3f,sizeof d);
memset(vis,0,sizeof vis);
priority_queue<int,vector<int>,cmp>q;
q.push(x);
d[x]=0;
while(!q.empty()){
int k=q.top();
q.pop();
if(vis[k])continue;
vis[k]=1;
for(int i=head[k];i!=-1;i=bian[i].next){
int v=bian[i].v;
int w=bian[i].w;
if(d[v]>d[k]+w){
d[v]=d[k]+w;
q.push(v);
ans2[v]=k;
}
}
}
}
void cmp(){
v.clear();
int p=e;
v.push_back(e);
while(ans1[p]!=0){
v.push_back(ans1[p]);
p=ans1[p];
}
sumlc=v;
}
//s->x->y->e
void cmp1(int x,int y){
v.clear();
int p=y;
v.push_back(p);
while(ans2[p]!=0){
v.push_back(ans2[p]);
p=ans2[p];
}
v.push_back(x);
p=x;
while(ans1[p]!=0){
v.push_back(ans1[p]);
p=ans1[p];
}
sumlc=v;
}
void solve(){
int flag=0;
while(cin>>n>>s>>e){
if(flag)cout<<endl;
flag=1;
init();
cin>>m;
for(int i=0;i<m;i++){
int x,y,z;
cin>>x>>y>>z;
add(x,y,z);add(y,x,z);
}
djst(s);
int minn=d[e];
for(int i=1;i<=n;i++){
d1[i]=d[i];
}
cmp();
djst1(e);
for(int i=1;i<=n;i++){
d2[i]=d[i];
}
int kk;
cin>>kk;
int f=0;
for(int i=0;i<kk;i++){
int x,y,z;
cin>>x>>y>>z;
if(d1[x]+z+d2[y]<minn){
minn=d1[x]+z+d2[y];f=x;
cmp1(x,y);
}else if(d1[y]+z+d2[x]<minn){
minn=d1[y]+z+d2[x];f=y;
cmp1(y,x);
}
}
for(int i=sumlc.size()-1;i>=0;i--){
cout<<sumlc[i];
if(i!=0)cout<<" ";
else cout<<endl;
}
if(f==0)cout<<"Ticket Not Used"<<endl;
else cout<<f<<endl;
cout<<minn<<endl;
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
// int _;
// cin>>_;
// while(_--){
solve();
// }
return 0;
}