pat甲级练习题 1003 emergency

通过该题学习数据结构图。

1.问题描述

给出N个城市,M条无向边。每个城市都有一定数目的救援小组,所有变边的权值知道。给出起点和终点,求从起点到终点的最短路径条数及最短路径上救援小组数目之和。如果有多条最短路径,则输出救援小组数目之和最大的(这样才可以方便调配)。

输入样例

1
2
3
4
5
6
7
8
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

输出样例

1
2 4

2.思路

这道题不仅边有权值,点也有权值。因此在计算最短的路径条数和最短路径上的点权之和的最大值。
使用w[u]记录从起点start到达u可以达到的最大点权之和;num[u]表示从起点s到达顶点u的最短路径的条数。

3.代码实现

C++或者C实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

#include <cstring>
#include <algorithm>

using namespace std;
const int MAXV = 510;
const int INF = 1000000000;


// G为邻接矩阵,weight为点权
// d[]记录最短距离,w[]记录最大点权之和,num[]记录最短路径条数
int N, M, start, ending, G[MAXV][MAXV], weight[MAXV];
int d[MAXV], w[MAXV], num[MAXV];
// vis[i]==true 表示顶点i已访问
bool vis[MAXV] = {false};

void (int start) {
fill(d, d + MAXV, INF);// 将最短距离的数组赋值为无穷大
memset(num, 0, sizeof(num)); // 对num数组全部填充0
memset(w, 0, sizeof(w)); // 对w数组全部填充0
d[start] = 0;
w[start] = weight[start];
num[start] = 1;
for (int i = 0; i < N; i++) {
int u = -1, MIN = INF;
for (int j = 0; j < N; j++) {
if (vis[j] == false && d[j] < MIN) {
u = j;
MIN = d[j];
}
}
// 找不到小于INF的d[u],说明剩下的顶点和起点start不连通
if (u == -1) return;
vis[u] = true;
for (int v = 0; v < N; v++) {
// 如果v没有被访问 && u能到达v && 以u为中介点可以使d[v]更优
if (vis[v] == false && G[u][v] != INF) {
if (d[u] + G[u][v] < d[v]) {
d[v] = d[u] + G[u][v];// 覆盖d[v]
w[v] = w[u] + weight[v];// 覆盖w[v]
num[v] = num[u];// 覆盖num[v]
} else if (d[u] + G[u][v] == d[v]) {
// 以u为中介点时点权值之和最大
if (w[u] + weight[v] > w[v]) {
// w[v]继承自w[u]
w[v] = w[u] + weight[v];
}
num[v] += num[u];
}
}
}
}
}

int main() {
scanf("%d%d%d%d", &N, &M, &start, &ending);
for (int i = 0; i < N; i++) {
// 读入点权
scanf("%d", &weight[i]);
}
int u, v;
// 初始化图
fill(G[0], G[0] + MAXV * MAXV, INF);
for (int i = 0; i < M; i++) {
scanf("%d%d", &u, &v);
// 读入边权
scanf("%d", &G[u][v]);
G[v][u] = G[u][v];
}
Dijkstra(start); // Dijkstra算法入口
printf("%d %dn", num[ending], w[ending]); // 最短距离条数,最短路径中的最大点权
return 0;
}

4.词汇积累

scattered:分散的;零散的;疏落的
call up:(给…)打电话;(陆、海、空军)征召…入伍;选中,挑选(…参加运动队)