先建图!!!
利用前后驱关系建立无向图。
因为边权全是1,所以每个点访问一次dfs就行了
维护最短路径——回溯(temp_path,path)
第一标尺:找经过站点最少的
第二标尺:找换乘次数最少的【计算换乘次数,与几号线有关】
(几号线:看成边权,因为只在换乘时用得到)
#include <bits/stdc++.h>
using namespace std;
int n,k;
int s1,s2;
vector<vector<int> > G(10000);
unordered_map<int,int> line; //i->j line[i*10000+j]
vector<int> temp_path,path;
int getTransfer(){
int ans=0,pre_transfer=-1;
for(int i=1;i<temp_path.size();i++){
if(pre_transfer!=-1 && line[temp_path[i-1]*10000+temp_path[i]]!=pre_transfer)
ans++;
pre_transfer=line[temp_path[i-1]*10000+temp_path[i]];
}
return ans;
}
int min_sum=INT_MAX,min_transfer=INT_MAX;
int visited[10000];
void dfs(int root,int sum){
if(sum>min_sum) return;
if(root==s2){//终点
if(sum<min_sum){
min_sum=sum;
min_transfer=getTransfer();
path=temp_path;
}else if(sum==min_sum && getTransfer()<min_transfer){
min_transfer=getTransfer();
path=temp_path;
}
return;
}
for(int i=0;i<G[root].size();i++){
if(visited[G[root][i]]==0){//未访问的邻接点
temp_path.push_back(G[root][i]),visited[G[root][i]]=1;
dfs(G[root][i],sum+1);
temp_path.pop_back(),visited[G[root][i]]=0;
}
}
}
void printPath(){
int preLine=-1,preStation=path[0];
for(int i=1;i<path.size();i++){
if(preLine!=-1 && line[path[i-1]*10000+path[i]]!=preLine){
//换乘
printf("Take Line#%d from %04d to %04d.\n",preLine,preStation,path[i-1]);
preStation=path[i-1];
}
preLine=line[path[i-1]*10000+path[i]];
}
//到终点了
printf("Take Line#%d from %04d to %04d.\n",preLine,preStation,s2);
}
int main(){
cin>>n;
int tk,ts,pre;
for(int i=1;i<=n;i++){
cin>>tk>>pre;
for(int j=1;j<tk;j++){
cin>>ts;
G[pre].push_back(ts);
G[ts].push_back(pre);//无向图
line[pre*10000+ts]=line[ts*10000+pre]=i;
pre=ts;
}
}
cin>>k;
for(int i=0;i<k;i++){
cin>>s1>>s2;
min_sum=INT_MAX,min_transfer=INT_MAX;
fill(visited,visited+10000,0);
temp_path.clear(),temp_path.push_back(s1);
dfs(s1,0);
cout<<min_sum<<endl;
printPath();
}
return 0;
}