版权声明:转载请注明出处:https://blog.csdn.net/qq1013459920 https://blog.csdn.net/qq1013459920/article/details/85110099
L2-001 紧急救援 (25 分)
作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。
输入格式:
输入第一行给出4个正整数N、M、S、D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0 ~ (N−1);M是快速道路的条数;S是出发地的城市编号;D是目的地的城市编号。
第二行给出N个正整数,其中第i个数是第i个城市的救援队的数目,数字间以空格分隔。随后的M行中,每行给出一条快速道路的信息,分别是:城市1、城市2、快速道路的长度,中间用空格分开,数字均为整数且不超过500。输入保证救援可行且最优解唯一。
输出格式:
第一行输出最短路径的条数和能够召集的最多的救援队数量。第二行输出从S到D的路径中经过的城市编号。数字间以空格分隔,输出结尾不能有多余空格。
输入样例:
4 5 0 3
20 30 40 10
0 1 1
1 3 2
0 3 3
0 2 2
2 3 2
输出样例:
2 60
0 1 3
Dijkstra的变形强化
AC Code:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<string>
#include<cctype>
#include<map>
#include<vector>
#include<string>
#include<queue>
#include<stack>
#define INF 0x3f3f3f3f
using namespace std;
static const int MAX_N = 1e5 + 5;
typedef long long ll;
int path[505][505], vv[505], dis[505]; //两点距离,结点权值,s到任意点最短距离
bool vis[505]; //标记
int maxval[505], pathcount[505], pre[505]; //最大结点和,最短路径数,前驱结点记录
int s, d, n;
void preprint(int e) { //最前结点开始遍历
if (pre[e] != -1) {
preprint(pre[e]);
printf("%d ", pre[e]);
}
}
void Dijkstra() {
for (int i = 0; i < n; i++) {
dis[i] = path[s][i];
}
//vis[s] = true;
maxval[s] = vv[s];
pathcount[s] = 1;
for (int i = 0; i < n; i++) {
int mins = INF, pres = s;
for (int j = 0; j < n; j++) {
if (!vis[j] && mins > dis[j]) {
mins = dis[j];
pres = j;
}
}
if (mins == INF) break;
vis[pres] = true;
for (int j = 0; j < n; j++) {
if (!vis[j]) {
if(dis[j] > dis[pres] + path[pres][j]){ //存在更短路
dis[j] = dis[pres] + path[pres][j];
maxval[j] = maxval[pres] + vv[j];
pathcount[j] = pathcount[pres];
pre[j] = pres;
}
else if (dis[j] == dis[pres] + path[pres][j]) { //最短路条数增加
pathcount[j] += pathcount[pres];
if (maxval[j] < maxval[pres] + vv[j]) { //存在更大权值
maxval[j] = maxval[pres] + vv[j];
pre[j] = pres;
}
}
}
}
}
}
int main(){
int m;
for (int i = 0; i < 505; i++) {
vis[i] = false;
maxval[i] = 0;
pathcount[i] = 0;
pre[i] = -1;
for (int j = 0; j < 505; j++) {
i == j ? path[i][j] = 0 : path[i][j] = path[j][i] = INF;
}
}
scanf("%d%d%d%d", &n, &m, &s, &d);
for (int i = 0; i < n; i++) scanf("%d", &vv[i]);
for (int i = 0; i < m; i++) {
int u, v, t;
scanf("%d%d%d", &u, &v, &t);
if (path[u][v] > t) {
path[u][v] = path[v][u] = t;
}
}
Dijkstra();
printf("%d %d\n", pathcount[d], maxval[d]); //最短路数与最大权值和
preprint(d); //打印路径
printf("%d\n", d);
return 0;
}