这个题之所以记录是因为这是我写过考察图论知识最全面的一道算法题,题意不是很难读懂,考察到了图论中最短路径–Dijstkra算法,拓展到最短路径条数、最大权值、最短路径等。我认为拿它来复习图论中最短路径这个知识点还是比较适合的
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
#include <bits/stdc++.h>
#include <vector>
using namespace std;
struct Graph{
int edge;
int weight;
Graph(int e, int w){
edge = e;
weight = w;
}
};
int main(){
int n, m, sx, sy;
cin>>n>>m>>sx>>sy;
int cs[n]; //记录救援队数目
int judge[n]; //记录该城市是否达到过
int dotlist[n]; //记录权值
int pre[n]; //记录行走路径
int path[n]; //记录最短路径条数
memset(path, 0, sizeof(path));
memset(pre, 0, sizeof(pre));
memset(dotlist, 0, sizeof(dotlist));
memset(judge, 0, sizeof(judge));
int res[n];
fill(res, res+n, 501);
for(int i = 0; i < n; i++){
cin>>cs[i];
}
vector<Graph> s[n];
for(int i = 0; i < m; i++){
int a, b, c;
cin>>a>>b>>c;
s[a].push_back(Graph(b, c));
s[b].push_back(Graph(a, c));
}
res[sx] = 0;
dotlist[sx] = cs[sx];
path[sx] = 1;
int flag = 0; //记录目前城市的下标
for(int i = 0; i < n; i++){
int min = 502;
for(int j = 0; j < n; j++){
if(!judge[j] && res[j] < min){
min = res[j];
flag = j;
}
}
int num = res[flag];
judge[flag] = 1;
for(int j = 0; j < s[flag].size(); j++){
int e = s[flag][j].edge;
int w = s[flag][j].weight;
if(!judge[e] && num + w < res[e]){
res[e] = num + w;
dotlist[e] = dotlist[flag] + cs[e];
pre[e] = flag;
path[e] = path[flag];
}else if(num + w == res[e]){
path[e] += path[flag];
if(dotlist[flag] + cs[e] > dotlist[e]){
dotlist[e] = dotlist[flag] + cs[e];
pre[e] = flag;
}
}
}
}
memset(res, 0, sizeof(res));
int r = sy, k = 0;
while(r != sx){
res[k++] = pre[r];
r = pre[r];
}
cout<<path[sy]<<' '<<dotlist[sy]<<endl;
for(int i = k-1; i >= 0; i--){
cout<<res[i]<<' ';
}
cout<<sy;
return 0;
}