✍个人博客:https://blog.csdn.net/Newin2020?spm=1011.2415.3001.5343
📚专栏地址:PAT题解集合
📝原题地址:题目详情 - 1003 Emergency (pintia.cn)
🔑中文翻译:紧急情况
📣专栏定位:为想考甲级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
题意
题目给定一张城市之间的关系图,道路是双向连通的,现在需要找到从源点 S
到终点 T
的最短路径。
另外,每个城市内有不同数量的救援队,没走到一个城市,这个城市的救援队就会跟着你去支援终点 T
,要计算出从从源点 S
到终点 T
在走最短路的情况下能召集到救援队数量的最大值。
第一行给定四个数,分别是城市数量
N
N
N 、道路数量
M
M
M 、起点 S
和终点 T
。
第二行给定每个城市的救援队数量,城市编号为 0 ∽ N − 1 0 \backsim N-1 0∽N−1 。
接下来的 M M M 行,给定从一个城市到另一个城市的路径长度。
思路
这道题我们可以用迪杰斯特拉算法求最短路,这个算法大致的思想就是每次都找到图中最短的那条路径,然后更新于它相邻边的路进值,具体的讲解可以参考我之前的博客,那里有更详细的图解。
这道题只需在原有的迪杰斯特拉算法模板上,顺便去更新每个结点的最大数量以及最短路的数量即可。
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 550;
int n, m, S, T;
int d[N][N];
int dist[N], sum[N], cnt[N], w[N];
bool st[N];
void dijkstra()
{
//初始化
memset(dist, 0x3f, sizeof dist);
sum[S] = w[S], cnt[S] = 1, dist[S] = S;
for (int i = 0; i < n; i++)
{
int t = -1;
for (int j = 0; j < n; j++) //找到一条最短路
if (!st[j] && (t == -1 || dist[t] > dist[j]))
t = j;
st[t] = true;
for (int j = 0; j < n; j++) //更新信息
if (dist[j] > dist[t] + d[t][j]) //如果出现更短的路
{
dist[j] = dist[t] + d[t][j];
cnt[j] = cnt[t];
sum[j] = sum[t] + w[j];
}
else if (dist[j] == dist[t] + d[t][j]) //如果发现相同的最短路
{
cnt[j] += cnt[t];
sum[j] = max(sum[j], sum[t] + w[j]);
}
}
}
int main()
{
cin >> n >> m >> S >> T;
for (int i = 0; i < n; i++) cin >> w[i]; //输入每个城市救援队数量
//输入每条道路
memset(d, 0x3f, sizeof d);
while (m--)
{
int a, b, c;
cin >> a >> b >> c;
d[a][b] = d[b][a] = min(d[a][b], c);
}
dijkstra(); //迪杰斯特拉算法
cout << cnt[T] << " " << sum[T] << endl;
return 0;
}