PAT 甲级考试【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
Dijkstra 算法
Dijkstra(/ˈdikstrɑ/或/ˈdɛikstrɑ/)算法由荷兰计算机科学家 E. W. Dijkstra 于 1956 年发现,1959 年公开发表。是一种求解 非负权图 上单源最短路径的算法。
过程
将结点分成两个集合:已确定最短路长度的点集(记为
集合)的和未确定最短路长度的点集(记为
集合)。一开始所有的点都属于
集合。
初始化
,其他点的
均为
。
然后重复这些操作:
- 从
集合中,选取一个最短路长度最小的结点,移到
集合中。 - 对那些刚刚被加入
集合的结点的所有出边执行松弛操作。
直到
集合为空,算法结束。
时间复杂度
有多种方法来维护 1 操作中最短路长度最小的结点,不同的实现导致了 Dijkstra 算法时间复杂度上的差异。
- 暴力:不使用任何数据结构进行维护,每次 2 操作执行完毕后,直接在
集合中暴力寻找最短路长度最小的结点。2 操作总时间复杂度为
,1 操作总时间复杂度为
,全过程的时间复杂度为
。 - 二叉堆:每成功松弛一条边
,就将
插入二叉堆中(如果
已经在二叉堆中,直接修改相应元素的权值即可),1 操作直接取堆顶结点即可。共计
次二叉堆上的插入(修改)操作,
次删除堆顶操作,而插入(修改)和删除的时间复杂度均为
,时间复杂度为
。 - 优先队列:和二叉堆类似,但使用优先队列时,如果同一个点的最短路被更新多次,因为先前更新时插入的元素不能被删除,也不能被修改,只能留在优先队列中,故优先队列内的元素个数是
的,时间复杂度为
。 - Fibonacci 堆:和前面二者类似,但 Fibonacci 堆插入的时间复杂度为
,故时间复杂度为
,时间复杂度最优。但因为 Fibonacci 堆较二叉堆不易实现,效率优势也不够大1,算法竞赛中较少使用。 - 线段树:和二叉堆原理类似,不过将每次成功松弛后插入二叉堆的操作改为在线段树上执行单点修改,而 1 操作则是线段树上的全局查询最小值。时间复杂度为
。
在稀疏图中,
,使用二叉堆实现的 Dijkstra 算法较 Bellman–Ford 算法具有较大的效率优势;而在稠密图中,
,这时候使用暴力做法较二叉堆实现更优。
正确性证明
下面用数学归纳法证明,在 所有边权值非负 的前提下,Dijkstra 算法的正确性2。
简单来说,我们要证明的,就是在执行 1 操作时,取出的结点
最短路均已经被确定,即满足
。
初始时
,假设成立。
接下来用反证法。
设
点为算法中第一个在加入
集合时不满足
的点。因为
点一定满足
,且它一定是第一个加入
集合的点,因此将
加入
集合前,
,如果不存在
到
的路径,则
,与假设矛盾。
于是一定存在路径
,其中
为
路径上第一个属于
集合的点,而
为
的前驱结点(显然
)。需要注意的是,可能存在
或
的情况,即
或
可能是空路径。
因为在
结点之前加入的结点都满足
,所以在
点加入到
集合时,有
,此时边
会被松弛,从而可以证明,将
加入到
时,一定有
。
下面证明
成立。在路径
中,因为图上所有边边权非负,因此
。从而
。但是因为
结点在 1 过程中被取出
集合时,
结点还没有被取出
集合,因此此时有
,从而得到
,这与
的假设矛盾,故假设不成立。
因此我们证明了,1 操作每次取出的点,其最短路均已经被确定。命题得证。
注意到证明过程中的关键不等式
是在图上所有边边权非负的情况下得出的。当图上存在负权边时,这一不等式不再成立,Dijkstra 算法的正确性将无法得到保证,算法可能会给出错误的结果。
实现
这里同时给出
的暴力做法实现和
的优先队列做法实现
PAT 甲级考试:
-----dfs+dijkstra算法。
- 先求出最短路径
- 再计算出最短路径数目并计算出路径上点权值的最大team和
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*; public class Main {
static int n, m;
static int source, target; static int[] number;
static int[][] matrix = new int[500][500]; static int[] distance; static int shorts; static int maxpeople = 0; static boolean[] traved; static List<Integer>[] adj; static int ways = 0; @SuppressWarnings("unchecked")
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] words = br.readLine().split("\\s+");
n = Integer.valueOf(words[0]);
m = Integer.valueOf(words[1]);
source = Integer.valueOf(words[2]);
target = Integer.valueOf(words[3]); number = new int[n];
words = br.readLine().split("\\s+");
for (int i = 0; i < n; i++) {
number[i] = Integer.valueOf(words[i]);
}
adj = new ArrayList[n];
for (int i = 0; i < n; i++) {
adj[i] = new ArrayList<>();
}
for (int i = 0; i < m; i++) {
int c1, c2, l;
words = br.readLine().split("\\s+");
c1 = Integer.valueOf(words[0]);
c2 = Integer.valueOf(words[1]);
l = Integer.valueOf(words[2]); matrix[c1][c2] = l;
matrix[c2][c1] = l; adj[c1].add(c2);
adj[c2].add(c1);
}
//bfs; distance = new int[n];
Arrays.fill(distance, Integer.MAX_VALUE / 2);
distance[source] = 0; PriorityQueue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return distance[o1] - distance[o2];
}
}); queue.add(source);
boolean[] visited = new boolean[n]; while (!queue.isEmpty()) {
int city = queue.poll(); if( visited[city]) continue; if (distance[city] >= Integer.MAX_VALUE / 2) {
break;
} visited[city] = true; for (int adjcity : adj[city]) {
if (distance[adjcity] > distance[city] + matrix[city][adjcity]) {
distance[adjcity] = distance[city] + matrix[city][adjcity];
queue.add(adjcity);
}
}
} shorts = distance[target];
//深度搜索
traved = new boolean[n];
traved[source] = true;
travel(source, 0, number[source], 0);
System.out.println(allpath.size() + " " + maxpeople);
} static Set<List<Integer>> allpath = new HashSet<>();
static List<Integer> path = new ArrayList<>(); static public void travel(int city, int d, int people, int depth) {
if (city == target && d == shorts) {
List<Integer> sortedpath = new ArrayList<>();
for (int x : path) {
sortedpath.add(x);
}
Collections.sort(sortedpath);
if (!allpath.contains(sortedpath)) {
ways++;
allpath.add(sortedpath);
} if (people > maxpeople) {
maxpeople = people;
}
return;
} if (d > shorts) {
return;
} for (int u : adj[city]) {
if (!traved[u]) {
traved[u] = true;
path.add(u);
travel(u, d + matrix[city][u], people + number[u], depth + 1);
traved[u] = false;
int x = path.remove(depth);
}
} }
}
PAT 甲级考试【1003 Emergency】的更多相关文章
- 【PAT甲级】1003 Emergency (25 分)(SPFA,DFS)
题意:n个点,m条双向边,每条边给出通过用时,每个点给出点上的人数,给出起点终点,求不同的最短路的数量以及最短路上最多能通过多少人.(N<=500) AAAAAccepted code: #in ...
- 2021.9.12周六PAT甲级考试复盘与总结
周六PAT甲级考试复盘与总结 先说结论:仍未步入"高手"行列:现在的学习节奏与方法是对的,有十万分的必要坚持下去. 题目 知识点 分数 T1 前缀和.二分 11 / 20 T2 排 ...
- pat甲级考试+pat1051+1056
同上一篇博客: 贪心题目我已经刷了将近30道了,由于那几天考驾照就没写,以后有空的时候补过来吧,都在codeblock里 pat的题也刷了点,acwing 的题也刷了点,基本都攒下了.以后也会慢慢补过 ...
- PAT 解题报告 1003. Emergency (25)
1003. Emergency (25) As an emergency rescue team leader of a city, you are given a special map of yo ...
- PAT 甲练习 1003 Emergency
1003 Emergency (25 分) As an emergency rescue team leader of a city, you are given a special map of y ...
- PAT (Advanced level) 1003. Emergency (25) Dijkstra
As an emergency rescue team leader of a city, you are given a special map of your country. The map s ...
- 2019年春PAT甲级考试
这次考试不是很理想,一道题目没能做完. 自己原因差不多三条: 1.自己实力不够,准备时间也有点仓促,自己没能做到每道题目都有清晰的思路. 2.考试的心理素质不行,因为设备原因东奔西跑浪费了挺多时间,自 ...
- PAT (Advanced Level) 1003. Emergency (25)
最短路+dfs 先找出可能在最短路上的边,这些边会构成一个DAG,然后在这个DAG上dfs一次就可以得到两个答案了. 也可以对DAG进行拓扑排序,然后DP求解. #include<iostrea ...
- 2019秋季PAT甲级_备考总结
2019 秋季 PAT 甲级 备考总结 在 2019/9/8 的 PAT 甲级考试中拿到了满分,考试题目的C++题解记录在这里,此处对备考过程和考试情况做一个总结.如果我的方法能帮助到碰巧点进来的有缘 ...
- PAT甲级满分有感
时间轴: 2017年,数据结构加入了我的课程清单. 2018年12月,我从网易云课堂下载了数据结构的所有课程视频(学校里没有网,只能离线看),开始一刷.一刷只看了视频,基本没有做题,看到AVL树的时候 ...
随机推荐
- 23.2 SEH之异常处理--《Windows核心编程》结构化异常处理
(structured exception handing)SEH 包含终止处理和异常处理.本章讨论异常处理. 当一个硬件或者软件异常被抛出的时候,操作系统会给我们程序一个查看异常类型的机会,并允 ...
- Sliver C2 实战 vulntarget-f
网络拓扑 host ip1 ip2 ubuntu(自用) 192.168.130.14 / centos 192.168.130.3 10.0.10.2 ubuntu1 10.0.10.3 10. ...
- ABC 312
前三题氵 D 给定一个由 (,?,) 组成的字符串.每个 ? 可以设定为任意括号.求有几种设定方法使得整个是合法括号序列. 套路,dp E 给定 \(n\) 个两两不相交的长方体,对每个长方体,求有多 ...
- jvm的简介
什么是jvm? java虚拟机就是二进制字节码的运行环境.我们可以把jvm看做是运行在不同系统上的一个软件应用的计算机,就比如说我们要打开图片,就得用看图软件,或者我们要对文件进行解压,是不是得用解压 ...
- JOISC 2023 纪录
记录一下 JOISC 2023 的做题记录 Day1 T1 Two Currencies 给定一棵树,在边上有总计 \(m\) 个检查站,经过一个检查站需要叫 \(1\) 枚金币或者若干枚银币.\(Q ...
- sensitive-word 敏感词/脏词开源工具-v.0.10.0-脏词分类标签支持
sensitive-word sensitive-word 基于 DFA 算法实现的高性能敏感词工具. 创作目的 实现一款好用敏感词工具. 基于 DFA 算法实现,目前敏感词库内容收录 6W+(源文件 ...
- 项目实战:Qt+Android模拟操作器(模拟操作app,打开,点击,输入,获取验证码等等)
若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/109313803各位读者,知识无穷而人力有穷,要 ...
- ubuntu 中 docker 每次都输入 sudo 命令
查看用户组及成员 sudo cat /etc/group | grep docker 可以添加docker组 sudo groupadd docker 添加用户到docker组 sudo gpassw ...
- 矩池云教程|体验 OpenAI 最近推出的 3D 生成模型 Shap-E!
Shap-E 是由 OpenAI 最近推出的3D生成模型,使用者可以通过简单的文字或图像进行三维模型的生成,OpenAI 认为相比于点云的生成模型Point-E,Shap-E的收敛更快.本文将展示如何 ...
- 07、Etcd 中Raft算法简介
本篇内容主要来源于自己学习的视频,如有侵权,请联系删除,谢谢. 思考: etcd是如何基于Raft来实现高可用.数据强-致性的? 1.什么是Raft算法 Raft 算法是现在分布式系统开发首选的共识算 ...