题目
旅行者的地图给出了高速公路沿线城市之间的距离,以及每条高速公路的成本。现在您应该编写一个程序来帮助旅行者决定他/她的出发城市和目的地之间的最短路径。如果这样的最短路径不是唯一的,则应该输出成本最低的路径,该路径保证唯一。
输入
每个输入文件包含一个测试用例。每个案例以一行包含 4 个正整数 N、M、S 和 D 开始,其中 N (≤500) 是城市的数量(因此城市的编号从 0 到 N-1); M是高速公路的数量; S 和 D 分别是起始城市和目的地城市。然后是 M 行,每行提供一条高速公路的信息,格式为:
City1 City2 Distance(距离) cost(成本)
其中数字均为不超过 500 的整数,并以空格分隔。
输出
对于每个测试用例,一行打印从起点到终点的最短路径上的城市,然后是总距离和路径的总成本。数字必须用空格分隔,并且输出末尾不能有多余的空格。
解题思路
先用Dijkstra求一下最短路径,然后在判断最短路径的过程中给路径数组pre做记录,根据是小于还是大于做不同情况处理,然后dfs从后往前,根据路径数组pre来做处理,在最短路径相同的情况下做成本的判断。最后输出的时候由于push_back是路径从后往前的放的,输出的时候要从后往前输出。
由于写的时候没太注意,定义变量的时候名字比较随意,望体谅。
#include <iostream>
#include <vector>
#include<algorithm>
#define maxnum 999
using namespace std;
int n,m,s,d;
int minpath=maxnum;
int book[505]={0};
vector<vector<int>>v(505,vector<int>(505,maxnum));//路径长度
vector<vector<int>>pr(505,vector<int>(505,maxnum));//路径费用
vector<vector<int>>pre(505,vector<int>(505,maxnum));//存储路径
vector<int>temp,num;//存储最短路径
void dfs(int v){
temp.push_back(v);
if(v==s){
int path=0;
//遍历temp中的路径总成本并与之前的相同路径的成本做比较
for(int i=0;i<temp.size()-1;i++){
int price=temp[i],price2=temp[i+1];
path+=pr[price][price2];
}
if(path<minpath){
minpath=path;
num=temp;
}
temp.pop_back();
return;
}
for(int i=0;i<pre[v].size();i++){
dfs(pre[v][i]);
}
temp.pop_back();
}
int main() {
scanf("%d %d %d %d",&n,&m,&s,&d);
for(int i=0;i<m;i++){
int num,num1,len,price;
cin>>num>>num1>>len>>price;
v[num][num1]=len;
v[num1][num]=len;
pr[num][num1]=price;
pr[num1][num]=price;
}
vector<int>dis(n,maxnum);
dis[s]=0;
for(int i=0;i<n;i++){
int u=-1,num=maxnum;
for(int j=0;j<n;j++){
if(book[j]==0&&dis[j]<num){
u=j;
num=dis[j];
}
}
if(u==-1)continue;
book[u]=1;
for(int j=0;j<n;j++){
if(v[u][j]!=maxnum&&book[j]==0){
//如果找到新的最短路径那就将之前储存的路径clear
if(v[u][j]+dis[u]<dis[j]){
dis[j]=v[u][j]+dis[u];
pre[j].clear();
pre[j].push_back(u);
}
//如果最短路径相等就直接储存,后续去dfs判断最小成本
else if(v[u][j]+dis[u]==dis[j]){
pre[j].push_back(u);
}
}
}
}
//放入终点,从后往前寻找路径
dfs(d);
for(int i=num.size()-1;i>=0;i--){
printf("%d ",num[i]);
}
printf("%d %d",dis[d],minpath);
return 0;
}