1087 All Roads Lead to Rome (30 分)
题目大意
有N个城市,M条无向边,从某个给定的起始城市出发,前往名为ROM的城市。每个城市(除了起始城市)都有一个点权(称为幸福值),和边权(每条边所需的花费)。求从起点到ROM所需要的最少花费,并输出其路径。如果路径有多条,给出幸福值最大的那条。如果仍然不唯一,选择路径上的城市平均幸福值最大的那条路径
核心思路
按照晴神算法笔记的模板,进行一次Dj+dfs即可求出。
不过需要注意的是,这里的顶点不是直接给出数字,而是给出三个大写字母组成的字符串。我们需要得到对应的整型的顶点编号才可以当作数组下标去使用。所以定义在读入权值的过程中,map<string, int> m1;和 map<int, string> m2;分别来存放键(城市名)、对应的值(城市编号,即结点编号) 和 键(城市编号,即结点编号) 、对应的值(城市名)
代码
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <map>
using namespace std;
const int MAXV = 210;//顶点编号可能从0~17575
const int INF = 1000000000;
int n, m;
int s1, s2;
int G[MAXV][MAXV];
int d[MAXV];
int vis[MAXV];
int weight[MAXV];//每一点的点权
vector<int> pre[MAXV];
// int w[MAXV];//从起点到顶点v的最短路径的权值(不需要,可以在dfs中的递归边界直接计算)
map<string, int> m1;
map<int, string> m2;
void dijkstra(int s){
//
fill(d, d + MAXV, INF);
d[s] = 0;
//
for (int i = 0; i < n;i++){
//
int u = -1, MIN = INF;
for (int j = 0; j < MAXV;j++){
if(vis[j]==false&&d[j]<MIN){
u = j;
MIN = d[j];
}
}
if(u==-1) return;
else vis[u]=true;
//
for (int v = 0; v < MAXV;v++){
if(G[u][v]!=INF&&vis[v]==false){
if(d[u]+G[u][v]<d[v]){
pre[v].clear();
pre[v].push_back(u);
d[v] = d[u] + G[u][v];
}else if(d[u]+G[u][v]==d[v]){
pre[v].push_back(u);
}
}
}
}
}
int cnt = 0;
int optVaule = 0;
vector<int> optPath, path;
void dfs(int v){
if(v==s1){
cnt++;
path.push_back(v);
int value = 0;
for (int i = path.size() - 1; i >=0;i--){
int pos = path[i];
value += weight[pos];
}
if(value>optVaule){
optVaule = value;
optPath = path;
}else if(value==optVaule){
if(1.0*value/path.size()>1.0*optVaule/optPath.size()){
optPath = path;
}
}
path.pop_back();
return;
}
path.push_back(v);
for (int i = 0; i < pre[v].size();i++){
dfs(pre[v][i]);
}
path.pop_back();
}
int main(){
//
cin >> n >> m;
string start;
cin >> start;
m1[start]=1;
m2[1]=start;
for (int i = 1; i <n;i++){
string ans;
cin>>ans>>weight[i+1];
m1[ans]=i+1;
m2[i+1]=ans;
}
fill(G[0], G[0] + MAXV * MAXV, INF);
string sa, sb;
int temp;
for(int i = 0; i < m; i++) {
cin >> sa >> sb >> temp;
G[m1[sa]][m1[sb]] = temp;
G[m1[sb]][m1[sa]] = temp;
}
//
s1=m1[start];
s2=m1["ROM"];
dijkstra(s1);
dfs(s2);
// //
cout << cnt << " " << d[s2] << " " << optVaule <<" "<<optVaule / (optPath.size()-1) << endl;
cout<<m2[optPath[optPath.size() - 1]];
for (int i = optPath.size() - 2; i >=0;i--){
int pos = optPath[i];
cout<<"->"<<m2[pos];
}
}