PAT---A1131 Subway Map (30分)

题意

给出n条线路,输入k组起点,终点,要求输出最优路径的信息。
最优路径:经过的站点最少,若站点数量相同则选择转乘最少的。

思路

看到题目就知道是比较繁琐的一题。

  • 最优路径选取:dfs 选择最优路径,有两种方法:一种是记录所有的路径,最后再遍历选出最优的路径;一种是直接选取,这里我选择的是第二种方法。
  • 输出最优路径信息是最繁琐的过程。

Sample Input:

4
7 1001 3212 1003 1204 1005 1306 7797
9 9988 2333 1204 2006 2005 2004 2003 2302 2001
13 3011 3812 3013 3001 1306 3003 2333 3066 3212 3008 2302 3010 3011
4 6666 8432 4011 1306
3
3011 3013
6666 2001
2004 3001

Sample Output:

2
Take Line#3 from 3011 to 3013.
10
Take Line#4 from 6666 to 1306.
Take Line#3 from 1306 to 2302.
Take Line#2 from 2302 to 2001.
6
Take Line#2 from 2004 to 1204.
Take Line#1 from 1204 to 1306.
Take Line#3 from 1306 to 3001.
#include "bits/stdc++.h"
using namespace std;
int a, b;
const int N = 10000;
vector<int> links[N];
int G[N][N];
int getLineId(int from, int to){
    return G[from][to];
}
vector<int> ans,temp;
int vis[N];
int cntTransfers(vector<int>& path){
    int pre = -1;
    int res = 0;
    for(int i=1;i<path.size();i++){
        int id = getLineId(path[i],path[i-1]);
        if (id != pre) pre = id, res ++;
    }
    return res;
}
void dfs(int id){
    if (vis[id] || (!ans.empty() && ans.size() <= temp.size()))  return;
    temp.push_back(id);
    if (id == b ) {
        if (
                ans.empty()
        || temp.size() < ans.size()
        || (temp.size() == ans.size() && cntTransfers(temp)<cntTransfers(ans))
        ) ans = vector<int>(temp);

        temp.pop_back();
        return;
    }
    vis[id] = 1;
    for(int t:links[id]) dfs(t);
    temp.pop_back();
    vis[id] = 0;
}
void show(){
    int line = -1; int from = ans[0];
    for(int i=1;i<ans.size();i++){
        if (line == -1) {
            line = getLineId(ans[i],ans[i-1]);
        } else if (getLineId(ans[i],ans[i-1]) != line ){
            printf("Take Line#%d from %04d to %04d.\n",line,from,ans[i-1]);
            line = getLineId(ans[i],ans[i-1]);
            from = ans[i-1];
        }
        if (i == ans.size() -1)
            printf("Take Line#%d from %04d to %04d.\n",line,from,ans[i]);
    }
}
int main(){
//     freopen("input.txt","r",stdin);
    int n; cin >> n;
    for (int i = 0; i < n; ++i) {
        int m; scanf("%d",&m); vector<int> line(m);
        for (int j = 0; j < m; ++j) scanf("%d",&line[j]);
        for (int j = 1; j < m; ++j) {
            links[line[j]].push_back(line[j-1]);
            links[line[j-1]].push_back(line[j]);
            G[line[j]][line[j-1]] = G[line[j-1]][line[j]] = i + 1;
        }
    }
    int k;  cin >> k;
    for (int i = 0; i < k; ++i) {
        scanf("%d%d",&a,&b);
        temp.clear(); ans.clear();
        dfs(a);
        cout << ans.size()-1 << endl;
        show();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值