【PAT】1131 Subway Map (30 分)

该博客介绍了一种利用深度优先搜索(DFS)算法寻找城市地铁线路中,从起点到终点经过站点最少且换乘次数最少的路径的方法。代码实现包括建立无向图,维护最短路径和换乘次数,并输出最优路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先建图!!!

利用前后驱关系建立无向图。

因为边权全是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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值