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;
}

 

posted @ 2018-08-08 20:05  seasonal  阅读(102)  评论(0编辑  收藏  举报