PAT A 1111 Online Map (30分)

一、题目概述

求解两条路径:
1、源点、汇点间最短距离路径,若路经距离相同,选择耗时更短者。
2、源点、汇点间耗时最短路径,若路径耗时相同,选择路线上结点更少者。

二、思路

两次Dijkstra算法。
代码量较大,注意不要出错。

三、代码

#include <cstdio>
#include <vector>
using namespace std;
#define INF 0x7FFFFFFF
int main()
{
    int N, M, c1, c2;
    scanf("%d %d", &N, &M);
    vector<vector<int>> D(N, vector<int>(N, INF)), T(N, vector<int>(N, INF));
    vector<int> vset_1(N, 0), vset_2(N, 0), dist(N, INF), time_1(N, INF), time_2(N, INF), cnt(N, 0), pre_1(N, -1), pre_2(N, -1), path_1, path_2;
    for(int i = 0, v1, v2, tag, d, t; i < M; ++i)
    {
        scanf("%d %d %d %d %d", &v1, &v2, &tag, &d, &t);
        D[v1][v2] = d;
        T[v1][v2] = t;
        if(!tag)
        {
            D[v2][v1] = d;
            T[v2][v1] = t;
        }
    }
    scanf("%d %d", &c1, &c2);
    dist[c1] = time_1[c1] = time_2[c1] = 0;
    for(int i = 0, Min, v; i < N; ++i)
    {
        Min = INF;
        for(int j = 0; j < N; ++j)
            if(!vset_1[j] && dist[j] < Min)
            {
                Min = dist[j];
                v = j;
            }
        if(Min == INF)
            break;
        vset_1[v] = 1;
        for(int j = 0; j < N; ++j)
            if(D[v][j] != INF)
                if(dist[v] + D[v][j] < dist[j] || (dist[v] + D[v][j] == dist[j] && time_1[v] + T[v][j] < time_1[j]))
                {
                    dist[j] = dist[v] + D[v][j];
                    time_1[j] = time_1[v] + T[v][j];
                    pre_1[j] = v;
                }
    }
    for(int i = c2; i != -1; i = pre_1[i])
        path_1.push_back(i);
    for(int i = 0, Min, v; i < N; ++i)
    {
        Min = INF;
        for(int j = 0; j < N; ++j)
            if(!vset_2[j] && time_2[j] < Min)
            {
                Min = time_2[j];
                v = j;
            }
        if(Min == INF)
            break;
        vset_2[v] = 1;
        for(int j = 0; j < N; ++j)
            if(T[v][j] != INF)
                if(time_2[v] + T[v][j] < time_2[j] || (time_2[v] + T[v][j] == time_2[j] && cnt[v] + 1 < cnt[j]))
                {
                    time_2[j] = time_2[v] + T[v][j];
                    cnt[j] = cnt[v] +1;
                    pre_2[j] = v;
                }
    }
    for(int i = c2; i != -1; i = pre_2[i])
        path_2.push_back(i);
    if(path_1 != path_2)
    {
        printf("Distance = %d: ", dist[c2]);
        for(int i = path_1.size() - 1; i >= 0; --i)
            printf("%d%s", path_1[i], i ? " -> ":"\n");
        printf("Time = %d: ", time_2[c2]);
        for(int i = path_2.size() - 1; i >= 0; --i)
            printf("%d%s", path_2[i], i ? " -> ":"");
        return 0;
    }
    printf("Distance = %d; Time = %d: ", dist[c2], time_2[c2]);
    for(int i = path_2.size() - 1; i >= 0; --i)
        printf("%d%s", path_2[i], i ? " -> ":"");
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值