PAT(图)——1030 Travel Plan (30 分)

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

题目大意:

给出城市到城市的距离和车费,输出起点到终点的最短路径,如果距离相同,取花钱最少的路径。

题目解析:

求单源最短路径显然要用迪杰斯特拉算法,题目要求输出路径,则要使用pre数组记录前驱结点,最后用递归方法反向输出。题目中不仅要考虑距离,还要考虑车费,也就是边权分为两种:在比较的时候,如果新路径的距离比老路径短,更新该点的前驱结点,原点到该点距离,车费;如果新路径距离和老路径一样,且新路径车费更少,更新pre,原点到该点车费。

具体代码:

#include<iostream>
#include<algorithm>
#include<climits>
using namespace std;
#define MAXN 550
int dis[MAXN];//start到i的距离
int spend[MAXN];//start到i的费用
int e[MAXN][MAXN];//i到j的距离
int cost[MAXN][MAXN];//i到j的费用
bool vis[MAXN]= {false}; //i点是否已经成为跳板
int pre[MAXN];
void dfs(int v){
	if(v==pre[v]){
		printf("%d ",v);
		return;
	}
	dfs(pre[v]);
	printf("%d ",v);
}
int main() {
	fill(dis,dis+MAXN,INT_MAX);
	fill(spend,spend+MAXN,INT_MAX);
	fill(e[0],e[0]+MAXN*MAXN,INT_MAX);
	fill(cost[0],cost[0]+MAXN*MAXN,INT_MAX);
	int n,m,start,end;
	scanf("%d%d%d%d",&n,&m,&start,&end);
	while(m--) {
		int City1,City2, Distance, Cost;
		scanf("%d%d%d%d",&City1,&City2,&Distance,&Cost);
		e[City1][City2]=e[City2][City1]=Distance;
		cost[City1][City2]=cost[City2][City1]=Cost;
	}
	dis[start]=0;
	spend[start]=0;
	pre[start]=start;
	for(int i=0; i<n; i++) {
		int k=-1,min=INT_MAX;
		for(int j=0; j<n; j++) {
			if(vis[j]==false&&dis[j]<min) {
				min=dis[j];
				k=j;
			}
		}
		if(k==-1) break;
		vis[k]=true;
		for(int j=0; j<n; j++) {
			if(vis[j]==false&&e[k][j]<INT_MAX) {
				if(e[k][j]+dis[k]<dis[j]) { //如果新路径比原来的路径距离短,更新
					pre[j]=k;
					spend[j]=spend[k]+cost[k][j];
					dis[j]=e[k][j]+dis[k];
				} else if(e[k][j]+dis[k]==dis[j]&&spend[k]+cost[k][j]<spend[j]) { //如果距离一样 花费更少
					pre[j]=k;
					spend[j]=spend[k]+cost[k][j];
				}
			}
		}
	}
	dfs(end);
	printf("%d %d",dis[end],spend[end]);
	return 0;
}
全部评论

相关推荐

11-18 09:44
Java
小白也想要offer:简历别放洋屁,搞不还还放错了,当然你投外企除外,以上纯属个人观点
点赞 评论 收藏
分享
09-29 17:44
已编辑
蔚来_测(准入职员工)
//鲨鱼辣椒:见不了了我实习了四个月上周再投筛选了一天就给我挂了
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务