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;
}
全部评论

相关推荐

湫湫湫不会java:先投着吧,大概率找不到实习,没实习的时候再加个项目,然后把个人评价和荣誉奖项删了,赶紧成为八股战神吧,没实习没学历,秋招机会估计不多,把握机会。或者说秋招时间去冲实习,春招冲offer,但是压力会比较大
点赞 评论 收藏
分享
头顶尖尖的程序员:我是26届的不太懂,25届不应该是找的正式工作吗?为什么还在找实习?大四还实习的话是为了能转正的的岗位吗
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
07-08 10:39
一个证都没&nbsp;我能填什么
程序员小白条:别人有,你为什么没有,还是这个道理,社会就是比较,竞争,淘汰,你要安逸,那么就要做好淘汰的准备
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务