题目
题目大意
给出城市数量n和路的数目k,和起点名称。然后给出剩下n - 1个城市名称及其对应的happy值,以及边的连通情况。规定“ROM”为终点名称。如果最短路径有多条,那么happy值最大的路径为最佳路径。要求输出从起点到终点的最短路径的数目,最短路径的长度,最短路径中最佳路径的happy值,以及该路径的平均happy值。再输出该路径所通过的节点。
思路
毫无疑问,定源点求最短路径用迪杰斯特拉,求重复路径的数目可以加一个num数组,happy数组相当于之前写过题目中的cost数组,再用path数组记录最短路径中每个节点的前驱节点。题目中的节点名字是3个字母,可以用map来处理每个节点名字到下标的映射。
代码
#include <iostream>
#include <vector>
#include <map>
#include <climits>
using namespace std;
int n, k, start;
map<string, int> mp; // 每个节点名字到索引的映射
map<int, string> mp2; // 每个节点索引到名字的映射
vector<int> happy; // happy值,起点值为0
int g[210][210] = {0}; // 图
vector<int> dist; // 记录最短路径
vector<int> path; // 记录最短路径中每个节点的前驱节点
vector<int> num; // 到每个节点的重复路径的个数
vector<int> happiness; // 到每个节点最短路径的happy累计值
vector<string> res; // 存储最佳路径经过的节点名称
void dijie(){
bool visited[210] = {false};
dist[0] = 0;
num[0] = 1;
for (int cnt = 0; cnt < n; cnt++){
int now = -1, minl = INT_MAX; // now为要激活的节点
for (int i = 0; i < n; i++){
if (!visited[i] && dist[i] < INT_MAX){
if (minl > dist[i]){
minl = dist[i];
now = i;
}
}
} // 找到要激活的节点
if (now == -1){
return;
} // 如果找不到,返回
visited[now] = true; // 激活节点
for (int i = 0; i < n; i++){
if (!visited[i] && g[now][i] < INT_MAX){
if (dist[i] > dist[now] + g[now][i]){
dist[i] = dist[now] + g[now][i];
happiness[i] = happiness[now] + happy[i];
num[i] = num[now]; // 继承重复路径的个数
path[i] = now; // 记录前驱节点
}else if (dist[i] == dist[now] + g[now][i]){
num[i] += num[now]; // 累加重复路径的个数
if (happiness[i] < happiness[now] + happy[i]){
happiness[i] = happiness[now] + happy[i];
path[i] = now; // 记录前驱节点
}
}
}
}
}
}
void printPath(int node){
if (node == 0){
res.push_back(mp2[0]);
return;
} // 如果为起始节点,则回溯完毕,返回
printPath(path[node]);
res.push_back(mp2[node]);
}
int main(){
cin >> n >> k;
happy.resize(n, 0);
int des; // 终点的下标
for (int i = 0; i < n; i++){
string name;
cin >> name;
if (name == "ROM"){
des = i;
}
mp[name] = i;
mp2[i] = name;
if (i != 0){
cin >> happy[i];
}
} // start为0
for (int i = 0; i < n; i++){
for (int j = 0; j < n; j++){
g[i][j] = (i == j) ? 0 : INT_MAX;
}
} // 初始化图
for (int i = 0; i < k; i++){
string c1, c2;
int dis;
cin >> c1 >> c2 >> dis;
g[mp[c1]][mp[c2]] = g[mp[c2]][mp[c1]] = dis;
} // 构建图
dist.resize(n, INT_MAX);
num.resize(n, 0);
path.resize(n, 0);
happiness.resize(n, 0);
dijie();
printPath(des);
int avgHappy = happiness[des] / ((int)res.size() - 1);
cout << num[des] << " " << dist[des] << " " << happiness[des] << " " << avgHappy << endl;
for (int i = 0; i < (int)res.size(); i++){
cout << res[i];
if (i != (int)res.size() - 1){
cout << "->";
}
}
cout << endl;
return 0;
}