PAT甲级 1111 在线地图

原题链接

输入我们的当前位置和目的地,在线地图就可以推荐一些行进路线。

现在你的工作是向用户推荐两条路线:一条是最短路线,另一条是最快路线。

保证任何询问的两地之间都存在至少一条路线。

输入格式
第一行包含两个整数 N 和 M,表示地图中共有 N 个路口(编号 0∼N−1)和 M 个街道。

接下来 M 行,每行描述一条街道,格式如下:

V1 V2 one-way length time
V1 和 V2 是两个路口的编号,表示这两个路口之间存在一条街道,one-way 如果为 1 则表示这条街道是单行道,只能从 V1 前往 V2。如果为 0 表示是双行道,可随意通行。 length 是街道的长度,time 是通过这条街道花费的时间。

最后一行,将给出起点和终点路口的编号。

输出格式
第一行输出路程最短的路线,并输出最短路程 D,格式如下:

Distance = D: source -> v1 -> ... -> destination
第二行输出用时最快的路线,并输出最短用时 T,格式如下:

Time = T: source -> w1 -> ... -> destination
如果最短路线不唯一,则输出用时最短的那条路线(保证唯一)。

扫描二维码关注公众号,回复: 14271683 查看本文章

如果最快路线不唯一,则输出经过路口最少的那条路线(保证唯一)。

如果最短路线和最快路线经过的路口序列完全相同,则以如下格式将两个信息输出在一行:

Distance = D; Time = T: source -> u1 -> ... -> destination
数据范围
2≤N≤500,
1≤M≤N(N−1)2,
每条道路的长度和用时都不超过 1000。
任意两个路口之间可能出现重复街道。(这一点和官网不同)

输入样例1:
10 15
0 1 0 1 1
8 0 0 1 1
4 8 1 1 1
3 4 0 3 2
3 9 1 4 1
0 6 0 1 1
7 5 1 2 1
8 5 1 2 1
2 3 0 2 2
2 1 1 1 1
1 3 0 3 1
1 4 0 1 1
9 7 1 3 1
5 1 0 5 2
6 5 1 1 2
3 5
输出样例1:
Distance = 6: 3 -> 4 -> 8 -> 5
Time = 3: 3 -> 1 -> 5
输入样例2:
7 9
0 4 1 1 1
1 6 1 1 3
2 6 1 1 1
2 5 1 2 2
3 0 0 1 1
3 1 1 1 3
3 2 1 1 2
4 5 0 2 2
6 5 1 1 2
3 5
输出样例2:
Distance = 3; Time = 4: 3 -> 2 -> 5

我的解法:

#include <bits/stdc++.h>
using namespace std;
const int N = 510;
int n, m, dist[N], dist_ext[N];
int d1[N][N], d2[N][N];
int S, T;
bool st[N];
int pre[N];
pair<int, string> dijkstra(int d1[][N], int d2[][N], int type){
    memset(dist, 0x3f, sizeof dist);
    memset(dist_ext, 0x3f, sizeof dist_ext);
    memset(st, 0, sizeof st);
    dist[S] = 0, dist_ext[S] = 0;
    for(int i = 0; i < n; i ++ ){
        int t = -1;
        for(int j = 0; j < n; j ++ ){
            if(!st[j] && (t == -1 || dist[t] > dist[j])) t = j;
        }
        st[t] = true;
        for(int j = 0; j < n; j ++ ){
            int w;
            if(type == 0){
                w = d2[t][j];
            }
            else w = 1;
            if(dist[j] > dist[t] + d1[t][j]){
                pre[j] = t;
                dist[j] = dist[t] + d1[t][j];
                dist_ext[j] = dist_ext[t] + w;
            }
            else if(dist[j] == dist[t] + d1[t][j]){
                if(dist_ext[j] > dist_ext[t] + w){
                    pre[j] = t;
                    dist_ext[j] = dist_ext[t] + w;
                }
            }
        }
        
    }
    pair<int, string> res;
    res.first = dist[T];
    res.second = to_string(S);
    vector <int> path;
    for(int i = T; i != S; i = pre[i]){
        path.push_back(i);
    }
    for(int i = path.size() - 1; i >= 0; i -- ){
        res.second += " -> " + to_string(path[i]);
    }
    return res;
}

int main(){
    memset(d1, 0x3f, sizeof d1);
    memset(d2, 0x3f, sizeof d2);
    cin >> n >> m;
    while(m -- ){
        int a, b, t, c, d;
        cin >> a >> b >> t >> c >> d;
        d1[a][b] = min(d1[a][b], c);
        d2[a][b] = min(d2[a][b], d);
        if(!t){
            d1[b][a] = min(d1[b][a], c);
            d2[b][a] = min(d2[b][a], d);
        }
    }
    cin >> S >> T;
    auto res1 = dijkstra(d1, d2, 0);
    auto res2 = dijkstra(d2, d1, 1);
    if(res1.second != res2.second){
        printf("Distance = %d: %s\n", res1.first, res1.second.c_str());
        printf("Time = %d: %s", res2.first, res2.second.c_str());
    }
    else{
        printf("Distance = %d; Time = %d: %s",res1.first, res2.first, res2.second.c_str());
    }
    return 0;
}

 收获:

最短路径的“路径”不一定只有路径,这里强调的是最少的概念,也可以是最少时间

由于本题要求最短路径(路径不唯一取最短时间)和最短时间(路径不唯一取最少节点),所以需要两次dijkstra(),我们可以为函数设置参数type,根据type类型设置额外条件w的内容。对于最短路径,w为时间;对于最短时间,w为1(结点数)。

猜你喜欢

转载自blog.csdn.net/weixin_45660485/article/details/125135180