思路:
1.将每站的邻站和与邻站在哪条地铁线记录下来;
2.bfs,搜索距离最近的站台,如果搜索到终点站且距离相等的站台搜索完毕即break;
3.用数组记录此站台是否被访问过,如果此站台被访问且它不是换乘站也不是终点站那就跳过它;
4.如果被访问的站台已经被访问过且它是终点站,我们需要注意比较换乘次数;
5.如果被访问的站台已经被访问且它是换乘站,我们不仅需要比较历史换乘次数,还要考虑往下一站是否需要换乘,不需要换乘的线路优先;
代码:
#include<iostream>
#include<queue>
#include<vector>
#include<unordered_map>
using namespace std;
int lnno[10000][10000];
unordered_map<int,vector<int>> mp;
struct node{
int path,dist,tnf;
};
unordered_map<int,node> nds;
void print(int end,int last,int now){
if(now==nds[now].path){
printf("Take Line#%d from %04d to %04d.
",lnno[last][now],now,end);
return;
}
if(last!=now&&lnno[last][now]!=lnno[now][nds[now].path]){
print(now,now,nds[now].path);
printf("Take Line#%d from %04d to %04d.
",lnno[last][now],now,end);
}
else print(end,now,nds[now].path);
}
int main(){
int n,m,k;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&k);
vector<int> sta(k);
for(int j=0;j<k;j++) scanf("%d",&sta[j]);
for(int j=0;j<k;j++){
if(j>0){
mp[sta[j]].push_back(sta[j-1]);
lnno[sta[j]][sta[j-1]]=i;
}
if(j<k-1){
mp[sta[j]].push_back(sta[j+1]);
lnno[sta[j]][sta[j+1]]=i;
}
}
}
scanf("%d",&k);
for(int i=0;i<k;i++){
int start,end;
scanf("%d%d",&start,&end);
unordered_map<int,int> isv;
nds.clear();
queue<int> q;
q.push(start);
isv[start]=1;
nds[start]={start,0,0};
for(int d=0,flag=0;!q.empty();q.pop()){
int f=q.front();
if(flag&&d<nds[f].dist) break;
for(auto e:mp[f]){
if(isv[e]==0) q.push(e);
if(e==end) flag=1;
int t=lnno[f][nds[f].path]==lnno[f][e]?nds[f].tnf:nds[f].tnf+1;
if(isv[e]++==0||(nds[e].dist==nds[f].dist+1&&nds[e].tnf>=t)) nds[e]={f,nds[f].dist+1,t};
}
d=nds[f].dist;
}
printf("%d
",nds[end].dist);
print(end,end,end);
}
return 0;
}