題意: 找出一條路線,使得對任何給定的起點和終點,可以找出中途經停站最少的路線;如果經停站一樣多,則取需要換乘線路次數最少的路線
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;
}