PAT甲级题库 1003 Emergency (25 分)

题目

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, C 1 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

思路

1,这道题目和求图的最短路径最关,因此理论上可以用迪杰斯特拉算法解决,当然迪杰斯特拉算法求得是最短路径,这里要求的是最短路径(途中要召集救援队员)以及最短路径的个数,这就需要我们对普通的迪杰斯特拉算法稍微做一些改变,考验我们对迪杰斯特拉算法的理解。
2,我们以前做迪杰斯特拉算法的时候知道,源点到终点的最短路径可能有长度相等的多条,这个算法里我们需要把最短路径的条数数出来,核心就是抓住每个最短路径长度一定相等这个信息。
3,在所有的最短路径中找到一个路线能尽可能多的召集救援队员,这就是我们想要的路线。
4,怎么数最短路径的条数?要知道迪杰斯特拉使用的是贪心算法,所以肯定不是以宏观的角度找到A到B的所有路线,然后数其中路径长度最短有几条。而是使用贪心算法,保证前面得到的子问题的解都是最优,后面包裹的更大子问题的解自然最优。为什么我们能想到贪心算法?将源点到任何城市结点都看作一个子问题,实际上我们观察一个图可以发现,源点到终点的解是一个路径,而这个路径也是由路径构成的,路径与路径之间是包含关系,即我们认为更大问题的最优解能够依托贪心得到的更小问题的解得出。
5,结合本题目根据贪心算法,我们应该能够想到源点到终点的可召集更多救援队员的个数,最优路线个数,和前面贪心得到的小问题的可召集更多救援队员的个数,最优路线的个数一定都是有关系的,所以我们要为每一个结点的子问题都设定两个变量存储召集的最多救援队员数,最短路径数。
6,再将该算法具体和迪杰斯特拉算法对应起来,我们发现最小的子问题是C1到C1点,然后第二小的子问题,第三小的子问题需要for循环比较得出。

for (int j = 0; j < N; j++)
		{
   
			if (!flag[j])
			{
   
				if (distance[j] < min_dis)
				{
   
					min_dis = distance[j];
					v = j;
				}
			}
		}//找到了当前子问题的最优路线长度

得出本次第i小的子问题以后,要为得出第i+1小的子问题做一些准备,具体到这个题目中就是根据本次找到的子问题的终点城市,其到其他临近城市的路径长度与原来的路径长度做对比更新现在的路径,这中间同时更新各个子问题的最多救援队个数,最短路径数,然后继续循环找到第i+1小的问题。我们要找的C1到C2是其中的一个子问题,不管他是多小或者多大的子问题,反正只要循环到第N个子问题(即最大问题)找出解,那么其他的子问题的解自然都找出了,我们只需要输出对应的解即可。

代码

#include<iostream>
#include<vector>
using namespace std;
//城市数量N,路的数量M
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值