1030 Travel Plan (30 分)
A traveler's map gives the distances between cities along the highways, together with the cost of each highway. Now you are supposed to write a program to help a traveler to decide the shortest path between his/her starting city and the destination. If such a shortest path is not unique, you are supposed to output the one with the minimum cost, which is guaranteed to be unique.
Input Specification:
Each input file contains one test case. Each case starts with a line containing 4 positive integers N, M, S, and D, where N (≤500) is the number of cities (and hence the cities are numbered from 0 to N−1); M is the number of highways; S and D are the starting and the destination cities, respectively. Then M lines follow, each provides the information of a highway, in the format:
City1 City2 Distance Cost
where the numbers are all integers no more than 500, and are separated by a space.
Output Specification:
For each test case, print in one line the cities along the shortest path from the starting point to the destination, followed by the total distance and the total cost of the path. The numbers must be separated by a space and there must be no extra space at the end of output.
Sample Input:
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20
Sample Output:
0 2 3 3 40
常规的dijkstra 求最短路径,最短路长度,和第二边权最小
注意:边权求的是最小值,对于最小值,其costValue作为比较的变量初始化需要初始化为无穷大INF
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXV=510;//最大点数
const int INF=1e9;
int n,m,Start,End;//城市数 道路数 起点 终点
int G[MAXV][MAXV],d[MAXV];
vector<int> pre[MAXV];//最短路径图
int cost[MAXV][MAXV],c[MAXV];//路边权花费
int vis[MAXV]={false};
//1.Dijkstra求最短路径
void Dijkstra(int s){
//初始化
fill(d,d+MAXV,INF);
d[s]=0;//别忘了
//pre不需要初始化
for(int i=0;i<n;i++){
int u=-1,MIN=INF;
for(int j=0;j<n;j++){
if(vis[j]==false&&d[j]<MIN){
MIN=d[j];
u=j;
}
}
if(u==-1) return;
vis[u]=true;
for(int v=0;v<n;v++){
if(vis[v]==false&&G[u][v]!=INF){
if(d[u]+G[u][v]<d[v]){//距离更短了
d[v]=d[u]+G[u][v];
pre[v].clear();
pre[v].push_back(u);
}else if(d[u]+G[u][v]==d[v]){
pre[v].push_back(u);
}
}
}
}
}
//2.DFS求第二标尺最优 此处求路径和花费即可
vector<int> tempPath,path;//临时路径和最终路径
int costValue=INF;//最终花费 求最短花费 因此初始花费要为无穷大 ★★★
// int disValue=-1; //总距离求个毛 不就是d[End] 本题就一个第二标尺 很简单 输出路径可能要DFS
void DFS(int v){//终点开始DFS
if(v==Start){//到达起点 递归边界
tempPath.push_back(v);
//求最小花费
int cvalue=0;
for(int i=tempPath.size()-1;i>0;i--){
int id=tempPath[i],idNext=tempPath[i-1];
cvalue+=cost[id][idNext];
}
if(cvalue<costValue){
costValue=cvalue;//更新最小花费和最优路径
path=tempPath;
}
tempPath.pop_back();
}
tempPath.push_back(v);//加入临时访问路径后面
for(int i=0;i<pre[v].size();i++){
DFS(pre[v][i]);//走到下一步 (DFS,到终点自动回退)
}
tempPath.pop_back();
}
int main(){
// freopen("input.txt","r",stdin);
int u,v,dis,cst;//u->v的距离dis和花费 cst;
cin>>n>>m>>Start>>End;
fill(G[0],G[0]+MAXV*MAXV,INF);
for(int i=0;i<m;i++){
cin>>u>>v>>dis>>cst;
G[u][v]=G[v][u]=dis;//起点终点随机 无向图
cost[u][v]=cost[v][u]=cst;
}
Dijkstra(Start);
//得到pre[n]再DFS
DFS(End);//终点开始DFS
//输出最短路径
for(int i=path.size()-1;i>=0;i--){
cout<<path[i]<<" ";
}
//输出最短距离和最小花费
cout<<d[End]<<" "<<costValue<<endl;
return 0;
}