【PAT A-1003】Emergency

PAT 甲级 1003. Emergency

题意概述

地图上有一些分散的城市,这些城市通过一些双向道路相连。地图上标出了每个城市的救援队数量以及每对城市之间的每条道路的长度。当从其他城市接到紧急电话时,你需要尽快到达该城市,同时在途中尽可能多地召集救援队。

输入输出格式

输入第一行包含 4 个正整数:N、M、C1、C2,分别表示城市数量(城市从 0 到 N-1 编号)、道路数量、当前所在的城市和要到达的城市。接下来一行包含 N 个整数,其中第 i 个整数是第 i 个城市中救援队的数量。接下来 M 行,每行以 c 1 , c 2 , L c_1,c_2,L c1,c2,L的格式描述一条道路,其中 c 1 , c 2 , L c_1,c_2,L c1,c2,L分别是该条道路相连的一对城市编号以及该道路的长度。题目保证从 C1 到 C2 至少存在一条路径。

在一行打印两个数字:C1 和 C2 之间最短路径的数量以及可能聚集的最大救援队数量。一行中的所有数字必须完全由一个空格隔开,并且在行尾不允许有多余的空格。

数据规模

N < = 500 N<=500 N<=500

前置知识

本题是经典的 Dijkstra 算法变形问题,建议系统学习过 Dijkstra 算法及其相关变形技巧之后再尝试解决本题。

C++代码

#include <bits/stdc++.h>
using namespace std;
using gg = long long;
struct Edge {
    gg to, cost;
    Edge(gg t, gg c) : to(t), cost(c) {}
};
const gg MAX = 505;
vector<vector<Edge>> graph(MAX);
vector<gg> city(MAX), dis(MAX, INT_MAX), pathNum(MAX), teamNum(MAX);
gg ni, mi, c1, c2;
using agg2 = array<gg, 2>;
void Dijkstra(gg s) {
    priority_queue<agg2, vector<agg2>, greater<agg2>> pq;
    dis[s] = 0;
    pathNum[s] = 1;
    teamNum[s] = city[s];
    pq.push({0, s});
    while (!pq.empty()) {
        auto p = pq.top();
        pq.pop();
        if (dis[p[1]] != p[0]) {
            continue;
        }
        for (auto& e : graph[p[1]]) {
            if (dis[e.to] > p[0] + e.cost) {
                dis[e.to] = p[0] + e.cost;
                pq.push({dis[e.to], e.to});
                pathNum[e.to] = pathNum[p[1]];
                teamNum[e.to] = teamNum[p[1]] + city[e.to];
            } else if (dis[e.to] == p[0] + e.cost) {
                pathNum[e.to] += pathNum[p[1]];
                teamNum[e.to] = max(teamNum[p[1]] + city[e.to], teamNum[e.to]);
            }
        }
    }
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> ni >> mi >> c1 >> c2;
    for (gg i = 0; i < ni; ++i) {
        cin >> city[i];
    }
    for (gg i = 0; i < mi; ++i) {
        gg a, b, c;
        cin >> a >> b >> c;
        graph[a].push_back(Edge(b, c));
        graph[b].push_back(Edge(a, c));
    }
    Dijkstra(c1);
    cout << pathNum[c2] << " " << teamNum[c2];
    return 0;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我真的不是cjc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值