PAT1131 Subway Map(DFS&&回溯)
题意:
找出一条路线,使得对任何给定的起点和终点,可以找出中途经停站最少的路线;如果经停站一样多,则取需要换乘线路次数最少的路线
思路:
这题就是用dfs+回溯写,我回溯写错了,找到终点的地方回溯了一次,递归回去又回溯了一次,这样就回溯了两次,看别人代码写了一下,这题还有一个地方要注意的就是这个换乘线路,我一开始是很随意的看该点有几条分支,超过2条说明为节点,但实际上这题求的是换乘的次数,完全可以经过节点但是不换乘,所以这里还要专门处理一下。
#include<bits/stdc++.h>
using namespace std;
const int maxn=10000;
vector<int> v[maxn];
unordered_map<int,int> line;
vector<int> path,temppath;
bool vis[maxn];
int s,e;
int mincnt,mintran;
int transforcnt(vector<int> a) {
int cnt = -1, preLine = 0;//开始必会换乘一次,所以cnt初值为-1
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 node,int cnt){
if(node==e){
if(cnt<mincnt){
mincnt=cnt;
mintran=transforcnt(temppath);
path=temppath;
}else if(cnt==mincnt&&mintran>transforcnt(temppath)){
mintran=transforcnt(temppath);
path=temppath;
}
return ;
}
for(int i=0;i<v[node].size();i++){
int nex=v[node][i];
if(vis[nex]==false){
vis[nex]=true;
temppath.push_back(nex);
dfs(nex,cnt+1);
vis[nex]=false;
temppath.pop_back();
}
}
}
int main(){
int n,m,k,pre,temp;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d%d",&m,&pre);
for(int j=1;j<m;j++){
scanf("%d",&temp);
v[pre].push_back(temp);
v[temp].push_back(pre);
line[pre*maxn+temp]=line[temp*maxn+pre]=i+1;
pre=temp;
}
}
scanf("%d",&k);
while(k--){
scanf("%d%d",&s,&e);
fill(vis,vis+maxn,false);
temppath.clear();
path.clear();
mincnt=maxn;
mintran=maxn;
temppath.push_back(s);
vis[s]=true;
dfs(s,0);
printf("%d\n",mincnt);
int preline=0,pretrans=s;
for(int j=1;j<path.size();j++){
if(line[path[j-1]*maxn+path[j]]!=preline){
if(preline!=0)
printf("Take Line#%d from %04d to %04d.\n", preline, pretrans, path[j-1]);
preline=line[path[j-1]*maxn+path[j]];
pretrans=path[j-1];
}
}
printf("Take Line#%d from %04d to %04d.\n", preline, pretrans, e);
}
return 0;
}