题目与翻译

1003 Emergency 紧急情况 (25分)

As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the length of each road between any pair of cities are marked on the map. When there is an emergency call to you from some other city, your job is to lead your men to the place as quickly as possible, and at the mean time, call up as many hands on the way as possible.

作为一个城市的紧急救援队队长,你会得到一张特殊的国家地图。这张地图显示了由一些道路连接起来的几个零散的城市。每个城市的救援队伍数量以及每一对城市之间的道路长度都在地图上标注出来。当其他城市给你打紧急电话时,你的工作就是带领你的人尽快赶到那个地方,同时,在路上尽可能多的召集人手。

Input Specification:

输入规格:

Each input file contains one test case. For each test case, the first line contains 4 positive integers: N (≤500) - the number of cities (and the cities are numbered from 0 to N−1), M - the number of roads, C1 and C2 - the cities that you are currently in and that you must save, respectively. The next line contains N integers, where the i-th integer is the number of rescue teams in the i-th city. Then M lines follow, each describes a road with three integers c1, c2 and L, which are the pair of cities connected by a road and the length of that road, respectively. It is guaranteed that there exists at least one path from C1 to C2.

每个输入文件包含一个测试用例。对于每个测试案例,第一行包含4个正整数: n (≤500)-城市数量(城市数量从0到 n-1) ,m-道路数量,c1和 c2-你目前所在的城市和你必须保存的城市。下一行包含 n 个整数,其中 i-th 整数表示第 i 城市救援队的数量。然后是 m 线,每条线描述一条有三个整数 c1,c2和 l 的道路,这三个整数分别是由一条道路连接起来的两个城市和这条道路的长度。它保证至少存在一条从 c1到 c2的路径。

Output Specification:

输出规格:

For each test case, print in one line two numbers: the number of different shortest paths between C1 and C2, and the maximum amount of rescue teams you can possibly gather. All the numbers in a line must be separated by exactly one space, and there is no extra space allowed at the end of a line.

对于每个测试用例,用一行打印两个数字: c1和 c2之间不同的最短路径的数量,以及您可能召集的救援队伍的最大数量。一行中的所有数字必须正好用一个空格隔开,并且在一行的末尾不允许有额外的空格。

Sample Input:

样本输入:

5 6 0 2
1 2 1 5 3
0 1 1
0 2 2
0 3 1
1 2 1
2 4 1
3 4 1

Sample Output:

示例输出:

2 4

理解与算法

城市,道路,路程长度,这几个要素很容易联想到图。

首先我们来定义需要的数据结构:

  • 起始节点到其他各个节点的距离数组,dis,当还无法到达某个节点时,就将这个节点的距离设置为无穷远
  • 起始节点到其他各个节点的最短路径的数量数组,初始值为0,除了到起始节点本身的路径数量为1
  • 起始节点到其他各个节点的能召集的最大救援队数量
  • 起始节点到其他各个节点的访问数组,代表是否访问过这个节点
vector<vector<int>> edge(N, vector<int>(N, INT_MAX));
// 到i顶点的距离
vector<int> dis(N, INT_MAX);
// c1和 c2之间不同的最短路径的数量
vector<int> roads(N, 0);
// 到i顶点的救援队的数量
vector<int> teams(N, 0);
// 是否访问过i顶点
vector<bool> visit(N, false);

因为我们有众多的节点需要遍历,所以不可避免地用到循环,确定循环前我们需要知道循环条件,很显然,每个节点至少要访问一次,此处的访问是指访问它的邻接链表,也就是从该点出发能够到达的其他节点

而后我们还要知道如何找到下一个访问的节点,图并不是线性的,图是网状结构,没有明确的先后关系,理想状态中,最佳的访问顺序是拓扑序,当一个节点被访问之后就拿掉所有的出边,再去寻找下一个没有入边的节点,理由是这样就不可能出现访问其他节点导致以前的最短路程出现问题。例如下面这个图:

如果从C1出发,先走C2,再走到C4之类的节点就会导致C1-C2这条边不是最短路程,而出现这个问题的原因就是因为直接走C2它的入度并不为0,而是1,因为C3还可以到C2!

但是维护一个入度数组十分复杂,代价较大,我们可以换一种方式,在遍历完一个节点之后我们选择下一个未被访问过的节点中,路程最近的节点,这个节点有可能不是初始节点的邻接节点,这样做的目的就是不可能从起始节点出发经过其他未访问的节点再到这个节点的路程小于当前的路程!

还是那上面这张图举个例子,C1-C3的距离为2,而C1-C2的距离为4,4 > 2是既定事实,不管怎么走只要经过C2再绕回C3就不可能出现路径更短的情况!

for (int j = 0; j < N; j++) {
// 找出没访问过的顶点中距离最近的点
if (!visit[j] && dis[j] < minn) {
u = j;
minn = dis[j];
}
}

然后我们再来寻找最短路径的最大数量以及救援队的数量。很显然,我们要先找到最短路径,方法就是用Dijkstra算法:遍历当前访问节点的所有邻接节点,如果路程比记录的路程更短,就覆盖原有数据:

if (dis[u] + edge[u][v] < dis[v]) {
dis[v] = dis[u] + edge[u][v];
// 因为找到了有更短路程的路径,就用新的路径的条数覆盖原有的路径条数
roads[v] = roads[u];
teams[v] = teams[u] + weight[v];
}

这里的u为当前访问节点,v为u的邻接节点。因为找到了更短的路,所以原本的路径都失效了,现在有效的路径是从u触发到v的路径,而根据题目的描述,两个城市之间只有一条路,所以上面的赋值语句实际含义为:

roads[v] = roads[u] * 1;

如果有多条路径,那可以把1换成路径的数量。

而当路程等于最短路程时,就相当于新发现了一条路,并且由于每个节点仅仅访问一次,所以不会有重复的问题,不需要考虑去重。

else if (dis[u] + edge[u][v] == dis[v]) {
// 如果v这个点没有被访问过,并且从起始点到v点的距离=从起始点到u再到v的距离
// 那就是说到相同的目的地,路程一样长,但是走过的路是不一样的,就把这些不同的路和原本的路径的数量相加。
roads[v] = roads[v] + roads[u];
if (teams[u] + weight[v] > teams[v]) {
teams[v] = teams[u] + weight[v];
}
}

因为到下个节点v经过的路径每一条都是完全不同的,所以可以直接相加,并且也是因为俩城市只有一条路,所以实际含义为:

roads[v] = roads[v] + roads[u] * 1;

如果这个最短路径能够携带的救援队数量比原来的要多,就更新原来的数据,因为最短路径都是一样长的,所以救援队并不需要考虑归属问题,我们只要求数量!

代码[1]

#include <iostream>
#include <vector>
#include <limits.h> using namespace std; int main() {
//读取第一行数据
int N, M, C1, C2;
cin >> N >> M >> C1 >> C2;
vector<int> weight(N, 0);
for (int i = 0; i < N; i++) {
cin >> weight[i];
} vector<vector<int>> edge(N, vector<int>(N, INT_MAX));
// 到i顶点的距离
vector<int> dis(N, INT_MAX);
// c1和 c2之间不同的最短路径的数量
vector<int> roads(N, 0);
// 到i顶点的救援队的数量
vector<int> teams(N, 0);
// 是否访问过i顶点
vector<bool> visit(N, false); //初始化边权值表
int c1, c2, L;
for (int i = 0; i < M; i++) {
cin >> c1 >> c2 >> L;
edge[c1][c2] = edge[c2][c1] = L;
}
dis[C1] = 0;
teams[C1] = weight[C1];
roads[C1] = 1; for (int i = 0; i < N; ++i) {
int u = -1, minn = INT_MAX;
for (int j = 0; j < N; j++) {
// 找出没访问过的顶点中距离最近的点
if (!visit[j] && dis[j] < minn) {
u = j;
minn = dis[j];
}
}
if (u == -1) break;
visit[u] = true;
for (int v = 0; v < N; v++) {
// 如果v这个点没有访问过,且u到v是有路径的,那么就有可能刷新最短距离。
if (!visit[v] && edge[u][v] != INT_MAX) {
if (dis[u] + edge[u][v] < dis[v]) {
dis[v] = dis[u] + edge[u][v];
// 因为找到了有更短路程的路径,就用新的路径的条数覆盖原有的路径条数
roads[v] = roads[u];
teams[v] = teams[u] + weight[v];
} else if (dis[u] + edge[u][v] == dis[v]) {
// 如果v这个点没有被访问过,并且从起始点到v点的距离=从起始点到u再到v的距离
// 那就是说到相同的目的地,路程一样长,但是走过的路是不一样的,就把这些不同的路和原本的路径的数量相加。
roads[v] = roads[v] + roads[u];
if (teams[u] + weight[v] > teams[v]) {
teams[v] = teams[u] + weight[v];
}
}
}
}
}
cout << roads[C2] << " " << teams[C2] << endl;
return 0;
}

  1. https://zhuanlan.zhihu.com/p/138001717

PAT Advanced 1003 Emergency 详解的更多相关文章

  1. PAT Advanced 1003 Emergency (25) [Dijkstra算法]

    题目 As an emergency rescue team leader of a city, you are given a special map of your country. The ma ...

  2. PAT甲级1003. Emergency

    PAT甲级1003. Emergency 题意: 作为一个城市的紧急救援队长,你将得到一个你所在国家的特别地图.该地图显示了几条分散的城市,连接着一些道路.每个城市的救援队数量和任何一对城市之间的每条 ...

  3. 图论 - PAT甲级 1003 Emergency C++

    PAT甲级 1003 Emergency C++ As an emergency rescue team leader of a city, you are given a special map o ...

  4. PAT 甲级 1003. Emergency (25)

    1003. Emergency (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue As an emerg ...

  5. PAT 甲级1003 Emergency (25)(25 分)(Dikjstra,也可以自己到自己!)

    As an emergency rescue team leader of a city, you are given a special map of your country. The map s ...

  6. PAT 甲级 1003 Emergency

    https://pintia.cn/problem-sets/994805342720868352/problems/994805523835109376 As an emergency rescue ...

  7. PAT (Advanced Level) Practise 1003 Emergency(SPFA+DFS)

    1003. Emergency (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue As an emerg ...

  8. 用Advanced Installer制作DotNetBar for Windows Forms 12.0.0.1_冰河之刃重打包版详解

    关于 DotNetBar for Windows Forms 12.0.0.1_冰河之刃重打包版 --------------------11.8.0.8_冰河之刃重打包版-------------- ...

  9. PAT 解题报告 1003. Emergency (25)

    1003. Emergency (25) As an emergency rescue team leader of a city, you are given a special map of yo ...

随机推荐

  1. JavaSE05-数组

    1.概念 同一种类型数据的集合.其实数组就是一个容器. 2.优点 可以自动给数组中的元素从0开始编号,方便操作这些元素. 3.格式 1 元素类型[] 数组名 = new 元素类型[元素个数或数组长度] ...

  2. 遍历出字母A-Z(a-z)的四种方式

    # 四种方式打印出A-Z(a-z) import string l1 = [chr(i) for i in range(ord("A"), ord("Z") + ...

  3. 3分钟快速搞懂Java的桥接方法

    什么是桥接方法? Java中的桥接方法(Bridge Method)是一种为了实现某些Java语言特性而由编译器自动生成的方法. 我们可以通过Method类的isBridge方法来判断一个方法是否是桥 ...

  4. Shell变量、函数

    上篇文章初步认识了一下shell脚本及其简单的案例,下面我们再来讲一下shell的进击部分. 一.变量 1.常用系统变量:($HOME.$SHELL.$PWD.$USER) 2.自定义变量: 2.1. ...

  5. 网站开发学习Python实现-Django学习-介绍(6.1.1)

    @ 目录 1.MVT 2.ORM 关于作者 1.MVT 主要的目的是为了快速,简便的开发数据库驱动的网站,强调代码的复用,多个组件可以很方便以插件的方式服务于整个框架,采用的是MVT设计模式(差不多的 ...

  6. IIS重写2.0 IIS伪静态 下载地址

    IIS重写2.0 IIS伪静态 下载地址 https://www.iis.net/downloads/microsoft/url-rewrite#additionalDownloads Downloa ...

  7. python初学者-使用for循环用四位数组成不同的数

    digits = (1,2,3,4) for i in digits: for j in digits: if j==i: continuefor k in digits: if k==i or k= ...

  8. jQuery 库中的 $() 是什么?

    概述: $() 函数是 jQuery() 函数的别称. $() 函数用于将任何对象包裹成 jQuery 对象,接着就被允许调用定义在 jQuery 对象上的多个不同方法. 可以将一个选择器字符串传入 ...

  9. webpack相关的问题

    随着现代前端开发的复杂度和规模越来越庞大,已经不能抛开工程化来独立开发了,如react的jsx代码必须编译后才能在浏览器中使用:又如sass和less的代码浏览器也是不支持的. 而如果摒弃了这些开发框 ...

  10. Linux 时间同步 05 chrony时间同步

    Linux 时间同步 05 chrony时间同步 目录 Linux 时间同步 05 chrony时间同步 chrony 的优势: chrony包介绍 安装chrony 配置与外部时间服务器进行时间同步 ...