1087 All Roads Lead to Rome (30 分)
Indeed there are many different tourist routes from our city to Rome. You are supposed to find your clients the route with the least cost while gaining the most happiness.
Input Specification:
Each input file contains one test case. For each case, the first line contains 2 positive integers N (2≤N≤200), the number of cities, and K, the total number of routes between pairs of cities; followed by the name of the starting city. The next N−1 lines each gives the name of a city and an integer that represents the happiness one can gain from that city, except the starting city. Then K lines follow, each describes a route between two cities in the format City1 City2 Cost
. Here the name of a city is a string of 3 capital English letters, and the destination is always ROM
which represents Rome.
Output Specification:
For each test case, we are supposed to find the route with the least cost. If such a route is not unique, the one with the maximum happiness will be recommanded. If such a route is still not unique, then we output the one with the maximum average happiness -- it is guaranteed by the judge that such a solution exists and is unique.
Hence in the first line of output, you must print 4 numbers: the number of different routes with the least cost, the cost, the happiness, and the average happiness (take the integer part only) of the recommanded route. Then in the next line, you are supposed to print the route in the format City1->City2->...->ROM
.
Sample Input:
6 7 HZH
ROM 100
PKN 40
GDN 55
PRS 95
BLN 80
ROM GDN 1
BLN ROM 1
HZH PKN 1
PRS ROM 2
BLN HZH 2
PKN GDN 1
HZH PRS 1
Sample Output:
3 3 195 97
HZH->PRS->ROM
思路 :
使用dijkstra算法求出满足题意的路径,
输出:1.满足题意最短路径数目(第一种方法直接通过dijkstra算法计算答案,第二种方法通过二维向量数组保存所有路径通过dfs筛选出满足题意的路径)
2.输出最短路径的权值(边权dis[end])
3.快乐值(点权w[end])
4.平均值 (通过快乐值 /路径结点总数) w[end]/ ( 结点 node[end])
具体代码实现:
#include<iostream>
#include<map>
#include<vector>
using namespace std;
const int inf = 0x3f3f3f;
const int maxsize = 220;
int n,k;
string from,to,fname,cname,rname[maxsize];//输入的城市名字,存放城市名字的数组,rename[i]表示第i个城市的名字 rename冲突
map<string,int> m;//将城市的字母依次转换为数字存放入map中
int h,cost;//h表示城市的快乐值
//w[i]表示点权(第i个城市的快乐值) happy[i] 表示从start到第i个点最短路径中的快乐值
//num[k]表示从start到第i个点最短路径条数
//node[i]表示从start到第i个点最短路径中的结点个数(当快乐值相等时 计算结点的个数)
int edge[maxsize][maxsize],dis[maxsize],w[maxsize],happy[maxsize],node[maxsize],num[maxsize];
int dispre[maxsize];
int revert=0;//将城市的字母名字转换为对应的数字
vector<int>dispath; //存放最终要输出的路径
bool visit[maxsize];
void disdfs(int end){ //将需要输出的路径存放入dispath中
// cout<<dispre[end]<<endl;
if(dispre[end]==end){
dispath.push_back(end);
return;
}
disdfs(dispre[end]);
dispath.push_back(end);
}
void dijkstra(int start){
dis[start]=0;
num[start]=1;//此时起始点最短路径为1
for(int i=0;i<n;i++){
int min=inf,u=-1;
for(int j=0;j<n;j++){
if(dis[j]<min && visit[j]==false){
min=dis[j];
u=j;
}
}
visit[u]=true;
if(min==inf) return;
for(int k=0;k<n;k++){
if(visit[k]==false && edge[u][k]!=inf){
if(dis[u]+edge[u][k] < dis[k]){//存在更短的路径
dis[k]=dis[u]+edge[u][k];
num[k]=num[u];//更新start到k的最短路径的条数
happy[k]=happy[u]+w[k];
node[k]=node[u]+1;
dispre[k]=u;
}else if(dis[u]+edge[u][k]==dis[k]){
num[k]=num[k]+num[u];//当存在相等的最短路径时,将k,u的最短路径总数相加
if(happy[u]+w[k] > happy[k]){
happy[k]=happy[u]+w[k];
node[k]=node[u]+1;
dispre[k]=u;
}else if(happy[u]+w[k]==happy[k] && node[k] > node[u]+1){
node[k]=node[u]+1;
dispre[k]=u;
}
}
}
}
}
}
int main(){
ios::sync_with_stdio(false);
fill(dis,dis+maxsize,inf);
fill(edge[0],edge[0]+maxsize*maxsize,inf);
cin>>n>>k>>fname;
m[fname]=revert;//将名字转换对应的数字
rname[revert++]=fname;//将第一个名字放入名字数组中
for(int i=0;i<n;i++){ //初始化存放路径的数组
dispre[i]=i;
}
for(int i=1;i<n;i++){ //i=1因为第一个名字已经被占用
cin>>cname>>h; //输入城市的名字和快乐值
m[cname]=revert;//将名字转换对应的数字
rname[revert++]=cname;//将名字放入对应下标(自己的名字的对应的数字)名字数组中
w[i]=h; //将点权(快乐值)加入点权数组中
}
for(int i=0;i<k;i++){
cin>>from>>to>>cost;
edge[m[from]][m[to]] = edge[m[to]][m[from]] = cost;
}
int start=0,end=m["ROM"];
dijkstra(start);
// for(int i=0;i<sizeof(dis)/sizeof(int);i++){ //测试dis数组
// cout<<dis[i]<<endl;
// }
// for(int i=0;i<n;i++){ //测试dis数组
// cout<<dis[i]<<endl;
// }
// cout<<end<<endl;
// cout<<dis[end]<<endl;
disdfs(end);
int avg = happy[end]/(node[end]);
cout<<num[end]<<" "<<dis[end]<<" "<<happy[end]<<" "<<avg<<endl;
for(int i=0;i<dispath.size();i++){
if(i!=0)
cout<<"->";
cout<<rname[dispath[i]];//将城市数字名字对应的字母名字输出;
}
return 0;
}