题意: 找出一条路线,使得对任何给定的起点和终点,可以找出中途经停站最少的路线;如果经停站一样多,则取需要换乘线路次数最少的路线
tip:DFS + map
分析:0.可以这样计算出一条线路的换乘次数:在line[10000][10000]的数组中保存每两个相邻站中间的线路是几号线~从头到尾遍历最终保存的路径,preLine为前一小段的线路编号,如果当前的结点和前一个结点组成的这条路的线路编号和preLine不同,说明有一个换乘,就将cnt+1,最后遍历完累加的cnt即是换乘的次数~1.可以这样计算出一条线路中途停站的次数:在dfs的时候有个变量cnt,表示当前路线是所需乘的第几个站,每次dfs时候将cnt+1表示向下遍历一层~cnt就是当前中途停站的次数~2.可以这样输出结果:和计算线路换乘次数的思路一样,每当preLine和当前Line值不同的时候就输出一句话~保存preTransfer表示上一个换乘站,最后不要忘记输出preTransfer和最后一个站之间的路即使最后一个站并不是换乘站
#include<iostream>
#include<vector>
#include<cstring>
#include<unordered_map>
using namespace std;
vector<int> s[10003];
int checked[10003]= {0};
int mincnt,mintransfer,ed;
unordered_map<int,int>line;
vector<int>path,temp;
int getcnt(vector<int> a) {//计算换乘数
int cnt=-1,preline=0;
for(int i=1; i<a.size(); ++i) {
if(line[a[i-1]*10000+a[i]]!=preline)
cnt++;
preline=line[a[i-1]*10000+a[i]];
}
return cnt;
}
void dfs(int start,int cnt) {
temp.push_back(start);
checked[start]=1;
if(cnt>mincnt)
return ;
if(start==ed) {
if(cnt==mincnt) {//站数相同比较换乘数
if(getcnt(temp)<mintransfer) {
path=temp;
mintransfer=getcnt(temp);
}
} else {
path=temp;
mincnt=cnt;
mintransfer=getcnt(temp);
}
return ;
}
for(auto i : s[start]) {
if(checked[i]==0) {
dfs(i,cnt+1);
temp.pop_back();
checked[i]=0;
}
}
}
int main() {
int n;
cin>>n;
for(int i=0; i<n; ++i) {
int m,prestation,tempstation;
cin>>m>>prestation;
for(int j=1; j<m; ++j) {
cin>>tempstation;
s[prestation].push_back(tempstation);
s[tempstation].push_back(prestation);
line[prestation*10000+tempstation]=line[tempstation*10000+prestation]=i+1;//每记录两个站之间的地铁号
prestation=tempstation;
}
}
int k;
cin>>k;
for(int i=0; i<k; ++i) {
int a;
cin>>a>>ed;
mincnt=1e7;
mintransfer=1e7;
memset(checked,0,sizeof(checked));
temp.clear();
dfs(a,0);
cout<<mincnt<<endl;
int preline=0,pretransfer=a;
for(int j=1; j<path.size(); ++j) {
if(line[path[j-1]*10000+path[j]]!=preline) {//与前一站地铁号不同就得换乘
if(preline)
printf("Take Line#%d from %04d to %04d.\n", preline, pretransfer, path[j-1]);
preline = line[path[j-1]*10000+path[j]];
pretransfer = path[j-1];
}
}
printf("Take Line#%d from %04d to %04d.\n", preline, pretransfer, ed);
}
return 0;
}