文章目录

  • 题目描述
  • 题意理解
  • 解题思路
  • 核心算法
  • 完整代码

题目描述

1003 Emergency
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.

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.

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

题意理解

  • (人工渣翻)作为城市的紧急救援队队长,你被给予了一份特殊的国家地图。地图展示了几个由道路连通起来的散落城市,并且标出了每个城市拥有的救援队数量、道路长度。当急救电话响起时,你的工作是带领你的队员以最快的速度赶到救援地点,同时你要尽可能多的叫上途径城市的救援队队员。
  • 输入第一行为四个正整数:N(城市数量),M(道路数量),C1(出发地),C2(目的地)。第二行输入N个整数,表示每个城市的救援人员数量(城市编号从0开始)
  • 你的输出包含两个数:最短路径的数量和能搜集到的人手的最大数量。数字之间以空格隔开,并且行末不能有多余空格或空行

解题思路

  • 这道题是很明显的Dijkstra算法的变形,实际不难,但首先要求学生对原始Dijkstra算法已经很熟练,如果还是不会写或者不理解原始的Dijkstra算法,还是先去巩固基础吧。
  • 原点已经给出,则只要进行一次Dijkstra就能得出答案,但是这道题要求的是计算最短路径的数量而不是最短路径的长度,同时在保证路径最短的同时要记录能搜集到的最多的人手数量,因此,除了原始的Dijkstra算法之外,我们还应该设置两个数组:一个用来记录从原点到该节点所能选择的最短路数量(num),另一个用来记录从原点到该节点所能搜集到的帮手的最大数量(teams),最后直接输出num[C2],teams[C2]就可以了
  • 图存储城市直接路径长度,如果不连通,就置为INFINITY(无限大),同时设置一个teamsInCity数组,存储每个城市所含救援队队员数量
  • 核心代码整体思路是很简单的,只要在更新最短路径的同时更新teams数组,然后再加一个if:如果发现当前路径长度与上一个最短路径长度相同,则num++,并且比较这条路所能搜集到的帮手数是否大于上一次记录的最大帮手数,如果更大就更新teams就行了

核心算法

  • 根据上述思路,我们可以写出以下伪代码(num,teams,vis已全初始化为0,dist已初始化全为INF):
void Dijkstra()
{初始化原点S,即出发城市的dist[S],num[S],teams[S]while (1) {查找还未被访问过的城市中路径最短的城市;如果找不到就说明已经无未被访问过的连通城市,则返回;访问当前城市;遍历所有城市 {if (如果未访问过 && 路径更短) {更新路径长度;更新路径数量;更新人手数量;}else if (如果未访问过 && 路径与最短路径长度相同) {更新路径数量;if (如果能搜集到更多人手)更新人手数量;}}}
}
  • 重点在于如何更新路径数量和更新人手数量,当第一次访问到该城市时,该城市的num一定为0,teams也为0。对于num,既然是第一次访问,那么到达该城市的路径数量一定等于到达该城市之前上一个城市(其前驱节点)的路径数量,如果后序又有其他最短路径能到达该城市,则它就会进入else-if,这时,该城市肯定就不是第一次途径了,它的num就不为0了,此时要做的就是将它原本的最短路径数加上当前前驱城市的路径数,即num[cur] += num[pre];对于teams则比较简单,比较它的大前提是路径首先得最短,所以当找到新最短路径跟dist一样直接更新就行,当最短路径相同时,比较该条路上能搜集到的人手是不是更多,是的话直接更新
  • 于是就能写出下面的代码:
void Dijkstra()
{dist[S] = 0;num[S] = 1;teams[S] = teamsInCity[S];while (1) {int u = -1, min = INF;for (int i = 0; i < N; i++)if (min > dist[i] && !vis[i]) {u = i;min = dist[i];}if (u == -1)return;vis[u] = true;for (int i = 0; i < N; i++)if (!vis[i] && dist[i] > dist[u] + map[u][i]) {dist[i] = dist[u] + map[u][i];num[i] = num[u];teams[i] = teamsInCity[i] + teams[u];}else if (!vis[i] && dist[i] == dist[u] + map[u][i]) {num[i] += num[u];if (teams[i] < teamsInCity[i] + teams[u])teams[i] = teamsInCity[i] + teams[u];}}
}
  • 核心代码写出来了其他就该怎么来怎么来了

完整代码

#include <iostream>
#define MAXN 500
#define INF 0xffffff
using namespace std;int N, M, S, D, teamsInCity[MAXN], map[MAXN][MAXN], num[MAXN] = { 0 }, dist[MAXN], teams[MAXN];
bool vis[MAXN] = { false };void Dijkstra()
{dist[S] = 0;num[S] = 1;teams[S] = teamsInCity[S];while (1) {int u = -1, min = INF;for (int i = 0; i < N; i++)if (min > dist[i] && !vis[i]) {u = i;min = dist[i];}if (u == -1)return;vis[u] = true;for (int i = 0; i < N; i++)if (!vis[i] && dist[i] > dist[u] + map[u][i]) {dist[i] = dist[u] + map[u][i];num[i] = num[u];teams[i] = teamsInCity[i] + teams[u];}else if (!vis[i] && dist[i] == dist[u] + map[u][i]) {num[i] += num[u];if (teams[i] < teamsInCity[i] + teams[u])teams[i] = teamsInCity[i] + teams[u];}}
}void Emergency()
{for (int i = 0; i < N; i++)dist[i] = INF;Dijkstra();cout << num[D] << ' ' << teams[D];
}int main()
{cin >> N >> M >> S >> D;for (int i = 0; i < N; i++)cin >> teamsInCity[i];for (int i = 0; i < N; i++)for (int j = 0; j < N; j++)map[i][j] = INF;for (int i = 0; i < M; i++) {int c1, c2, len;cin >> c1 >> c2 >> len;map[c2][c1] = map[c1][c2] = len;}Emergency();return 0;
}

1003 Emergency 题目解析相关推荐

  1. PAT甲级1003 Emergency:[C++题解]dijkstra求最短路、最短路条数

    文章目录 题目分析 题目链接 题目分析 分析:求单源最短路,使用dijkstra()算法. 最短路的条数,和最短路中 人数最多的一条,输出最多人数. 本题点比较少,使用邻接矩阵d[N][N]来存. a ...

  2. Mysql窗口函数 (知识点梳理+题目解析+面试实战)(四万字长文,一文读懂,建议收藏后食用)

    前言: 本文章是原创50篇时开启的纪念作,之前的文章基本5000字,而本篇约4.5万字,真一篇顶九篇. 窗口函数作为Mysql 8的新特性以及面试笔试的重点,掌握并且进行来练习是非常有必要的.本文章详 ...

  3. 1003 Emergency (25 分)

    1003 Emergency (25 分) 题目大意 n个城市m条路,每个城市有救援小组,所有的边的边权已知.给定起点和终点,求从起点到终点的最短路径条数以及最短路径上的救援小组数目之和.如果有多条就 ...

  4. PAT甲级1003 Emergency Dijkstra算法(堆优化版/朴素版)

    前言   最近花了很多的时间在写JAVA项目上面,疏忽了算法和数据结构的学习.最近突然醒悟基础更为重要,打算从今天开始每天抽出一些时间做下PAT甲级的题目.现有题库的前两题很简单,从第三题开始吧. 题 ...

  5. 电子学会青少年编程等级考试Python一级题目解析12

    Python一级题目解析 1.题目(2021.03) 写一个计算长方形面积的程序,并对每行代码进行相应的注释,要求如下: (1)采用多行注释,说明程序的功能(如下): "计算长方形的面积 并 ...

  6. 电子学会青少年编程等级考试Python一级题目解析10

    Python一级题目解析 1.题目 下面代码的执行结果是() a = 123456789 b = "*" print("{0:{2}>{1},}\n{0:{2}^{ ...

  7. 电子学会青少年编程等级考试Python一级题目解析11

    Python一级题目解析 题目 (1)下列哪个不是Python的保留字?( )[2020.06] A. if B. or C. do D. for (2)下面哪一个不是Python的保留字?( )[2 ...

  8. 电子学会青少年编程等级考试Python一级题目解析03

    「青少年编程竞赛交流群」已成立(适合6至18周岁的青少年),公众号后台回复[Scratch]或[Python],即可进入.如果加入了之前的社群不需要重复加入. Python一级题目解析 1.题目[20 ...

  9. 实验楼python挑战答案_楼赛第1期-Linux项目挑战 题目解析

    楼赛是实验楼新上线的项目挑战.不同于侧重算法的 OJ.ACM一类的,楼赛考验的是动手能力,分析和解决问题的能力.这些正是实验楼的动手实践学IT理念所推崇的. 作为实验楼第一次常规周赛,本次三道题目有很 ...

最新文章

  1. LSGO软件技术团队招新
  2. flume采集数据报错问题解决
  3. oracle中v$database视图详解
  4. python datatime 平均值_python求数据的时间平均
  5. 32命令模式(Command Pattern)
  6. java substring_java 中 substring()方法
  7. 对NVM区的合理使用
  8. iOS AddressBook
  9. CF838D Airplane Arrangements
  10. 五环电阻和四环电阻的区别是什么
  11. 笔记本外接显示器感觉鼠标有延迟解决办法
  12. finalize()的真正用法及作用
  13. omap3630 linux i2c总线驱动分析,OMAP3630 Linux I2C总线驱动分析
  14. 【图形化安装】EVE-NG模拟器的安装
  15. Mysql数据库MMM实现高可用架构
  16. 2021年中国乳胶床垫市场趋势报告、技术动态创新及2027年市场预测
  17. matlab的符号变量sym,syms
  18. 使用vue+echarts快速进行全国地图与各省市地图联动(下钻地图), 引入省份js文件
  19. matlab里面gtophat什么意思,MATLAB图象处理函数
  20. 多重背包问题的二进制优化(C语言)

热门文章

  1. 微软笔试问题总结,吃一堑长一智
  2. FATE单机部署遇到的问题
  3. 我逛了一下这个终身教育平台。哎,一言难尽啊!
  4. 基于FPGA平台RISCV架构的SOC应用系统设计3
  5. 云服务器的端口开放问题
  6. linux命令 mv -v,linux中的mv命令
  7. unity 材质球无法编辑_【每天一个Unity技巧】批量修改材质球的主贴图和添加法线贴图...
  8. azkaban 安装 使用
  9. 学会python可以做什么兼职,能做兼职吗
  10. 现货黄金买卖技巧_价格振荡指标(PPO)