#1111. Online Map【单源最短路 + Dijkstra】

原题链接

Problem Description:

Input our current position and a destination, an online map can recommend several paths. Now your job is to recommend two paths to your user: one is the shortest, and the other is the fastest. It is guaranteed that a path exists for any request.

Input Specification:

Each input file contains one test case. For each case, the first line gives two positive integers N N N ( 2 ≤ N ≤ 500 2\leq N\leq 500 2N500), and M M M, being the total number of streets intersections on a map, and the number of streets, respectively. Then M M M lines follow, each describes a street in the format:

V1 V2 one-way length time

where V1 and V2 are the indices (from 0 to N − 1 N−1 N1) of the two ends of the street; one-way is 1 if the street is one-way from V1 to V2, or 0 if not; length is the length of the street; and time is the time taken to pass the street.

Finally a pair of source and destination is given.

Output Specification:

For each case, first print the shortest path from the source to the destination with distance D in the format:

Distance = D: source -> v1 -> ... -> destination

Then in the next line print the fastest path with total time T:

Time = T: source -> w1 -> ... -> destination

In case the shortest path is not unique, output the fastest one among the shortest paths, which is guaranteed to be unique. In case the fastest path is not unique, output the one that passes through the fewest intersections, which is guaranteed to be unique.

In case the shortest and the fastest paths are identical, print them in one line in the format:

Distance = D; Time = T: source -> u1 -> ... -> destination

Sample Input 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

Sample Output 1:

Distance = 6: 3 -> 4 -> 8 -> 5
Time = 3: 3 -> 1 -> 5

Sample Input 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

Sample Output 2:

Distance = 3; Time = 4: 3 -> 2 -> 5

Problem Analysis:

本题涉及到多关键字单源最短路,但是可以利用设置参数,只需写一个 Dijkstra。详见代码注释。

Code

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 510, M = N * N;

int n, m, S, T;
int h[N], e[M], ne[M], w1[M], w2[M], idx;
int dist1[N], dist2[N], pre[N];
bool st[N];

void add(int a, int b, int c, int d)
{
    
    
    e[idx] = b, w1[idx] = c, w2[idx] = d, ne[idx] = h[a], h[a] = idx ++ ;
}
// dijkstra返回两个东西,第一个是最短距离,第二个是路线;C++中数组作为参数时,第一维长度可以不写
pair<int, string> dijkstra(int w1[], int w2[], int type) // 第一关键字,第二关键字
{
    
    
    memset(dist1, 0x3f, sizeof dist1); // dist1 用于第一关键字更新的结果
    memset(dist2, 0x3f, sizeof dist2); // dist2 用于第二关键字更新的结果    
    memset(st, 0, sizeof st);
    dist1[S] = dist2[S] = 0;

    for (int i = 0; i < n; i ++ )
    {
    
    
        int t = -1;
        for (int j = 0; j < n; j ++ )
            if (!st[j] && (t == -1 || dist1[t] > dist1[j]))
                t = j;
        
        st[t] = true;
        for (int u = h[t]; ~u; u = ne[u])
        {
    
    
            int j = e[u];

            int cost; // 第二关键字的权值
            if (type == 0) cost = w2[u]; // 如果第一关键字是最短距离,那么第二关键字就应该是最短时间,所以权值就应该是 w2[u]
            else cost = 1; // 如果第一关键字是最短时间,那么第二关键字就应该是节点数量,权值应为 1

            if (dist1[j] > dist1[t] + w1[u])
            {
    
    
                dist1[j] = dist1[t] + w1[u];
                dist2[j] = dist2[t] + cost;
                pre[j] = t;
            }
            else if (dist1[j] == dist1[t] + w1[u])
            {
    
    
                if (dist2[j] > dist2[t] + cost)
                {
    
    
                    dist2[j] = dist2[t] + cost;
                    pre[j] = t;
                }
            }
        }
    }

    vector<int> path;
    for (int i = T; i != S; i = pre[i]) path.push_back(i);

    pair<int, string> res;
    res.first = dist1[T];
    res.second = to_string(S);

    for (int i = path.size() - 1; i >= 0; i -- )
        res.second += " -> " + to_string(path[i]);
    return res;   
}

int main()
{
    
    
    cin >> n >> m;

    memset(h, -1, sizeof h);

    while (m -- )
    {
    
    
        int a, b, t, c, d;
        scanf("%d%d%d%d%d", &a, &b, &t, &c, &d);
        add(a, b, c, d);
        if (!t) add(b, a, c, d);
    }

    cin >> S >> T;

    auto A = dijkstra(w1, w2, 0); // w1 是距离, w2 是时间
    auto B = dijkstra(w2, w1, 1); 

    if (A.second != B.second) 
    {
    
    
        printf("Distance = %d: %s\n", A.first, A.second.c_str());
        printf("Time = %d: %s\n", B.first, B.second.c_str());
    }
    else // 如果路径序列相同,则输出在同一行
    {
    
    
        printf("Distance = %d; Time = %d: %s\n", A.first, B.first, A.second.c_str());
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/geraltofrivia123/article/details/121046935