本人即将迎来第二次csp考试,准备提前刷刷题,刷题之前看到了之前做的PAT甲级的题目,又重新浏览了一遍,特来记录。
以下是题目:
这里给出本小菜鸡的小代码,如有大佬们有更好的解题思路可以一起讨论丫。
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
int n, m, s, d;
int val[550]; //权值,城市的救援队数目
int dis[550][550]; //两城市之间距离
int flag[550]; //城市是否被访问
int sum[550]; //到每个城市的路数
int jc[550]; //最大救援队数目
int length[550]; //到原点长度
int pre[550]; //前一城市
void Dijkstra() {
int tem1, tem2;
for (tem1 = 0; tem1 < n; tem1++) {
int min_length = 999999999, sign = s;
for (int i = 0; i < n; i++) { //找未被访问中路径最短的
if (flag[i] == 0 && min_length > length[i]) {
min_length = length[i];
sign = i;
}
}
flag[sign] = 1; //修改访问标记
for (tem2 = 0; tem2 < n; tem2++) {
if (flag[tem2] == 0) {
if (length[tem2] > length[sign] + dis[sign][tem2]) { 若存在更短路径
length[tem2] = length[sign] + dis[sign][tem2];
jc[tem2] = jc[sign] + val[tem2];
pre[tem2] = sign;
sum[tem2] = sum[sign];
}
else if (length[tem2] == length[sign] + dis[sign][tem2]) {
if (length[tem2] != 999999999) {
sum[tem2] += sum[sign];
if (jc[tem2] < jc[sign] + val[tem2]) {
jc[tem2] = jc[sign] + val[tem2];
pre[tem2] = sign;
}
}
else continue;
}
}
}
}
}
void prpath(int h) {
if (pre[h] != -1) {
prpath(pre[h]);
cout << pre[h] << " ";
}
}
int main() {
cin >> n >> m >> s >> d;
for (int i = 0; i < n; i++)
cin >> val[i];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (i == j) dis[i][j] = 0;
else dis[i][j] = 999999999;
for (int i = 0; i < m; i++) {
int a, b, c;
cin >> a >> b >> c;
dis[a][b] = c;
dis[b][a] = c;
}
for (int i = 0; i < n; i++) {
flag[i] = 0;
sum[i] = 0;
jc[i] = 0;
length[i] = 999999999;
pre[i] = -1;
}
//起点为s
length[s] = 0;
flag[s] = 1;
sum[s] = 1;
jc[s] = val[s];
Dijkstra();
cout << sum[d] << " " << jc[d] << endl;
prpath(d);
cout << d;
return 0;
}