PTA 一 天梯地图

本题要求你实现一个天梯赛专属在线地图,队员输入自己学校所在地和赛场地点后,该地图应该推荐两条路线:一条是最快到达路线;一条是最短距离的路线。题目保证对任意的查询请求,地图上都至少存在一条可达路线。

输入格式:

输入在第一行给出两个正整数N(2 \le N \le 500)和M,分别为地图中所有标记地点的个数和连接地点的道路条数。随后M行,每行按如下格式给出一条道路的信息:

V1 V2 one-way length time

其中V1V2是道路的两个端点的编号(从0到N-1);如果该道路是从V1V2的单行线,则one-way为1,否则为0;length是道路的长度;time是通过该路所需要的时间。最后给出一对起点和终点的编号。

输出格式:

首先按下列格式输出最快到达的时间T和用节点编号表示的路线:

Time = T: 起点 => 节点1 => ... => 终点

然后在下一行按下列格式输出最短距离D和用节点编号表示的路线:

Distance = D: 起点 => 节点1 => ... => 终点

如果最快到达路线不唯一,则输出几条最快路线中最短的那条,题目保证这条路线是唯一的。而如果最短距离的路线不唯一,则输出途径节点数最少的那条,题目保证这条路线是唯一的。

如果这两条路线是完全一样的,则按下列格式输出:

Time = T; Distance = D: 起点 => 节点1 => ... => 终点

输入样例1:

10 15
0 1 0 1 1
8 0 0 1 1
4 8 1 1 1
5 4 0 2 3
5 9 1 1 4
0 6 0 1 1
7 3 1 1 2
8 3 1 1 2
2 5 0 2 2
2 1 1 1 1
1 5 0 1 3
1 4 0 1 1
9 7 1 1 3
3 1 0 2 5
6 3 1 2 1
5 3

输出样例1:

Time = 6: 5 => 4 => 8 => 3
Distance = 3: 5 => 1 => 3

输入样例2:

7 9
0 4 1 1 1
1 6 1 3 1
2 6 1 1 1
2 5 1 2 2
3 0 0 1 1
3 1 1 3 1
3 2 1 2 1
4 5 0 2 2
6 5 1 2 1
3 5

输出样例2:

Time = 3; Distance = 4: 3 => 2 => 5

算法思路:单源最短路径拓展了一下

#include<stdio.h>
#include<stack>
using namespace std;

const int MAX = 1000000;
int mapl[500][500];
int mapt[500][500];
int vis[500];
int pre[500];
int dis[500];
int tim[500];
int n;

void init() {
	int i;
	for (i = 0; i<n; i++) {
		vis[i] = false;
		dis[i] = MAX;
		tim[i] = MAX;
	}
}

void dijkstraForTime(int source, int dest) {
	init();
	int i;
	int u = source;
	tim[u] = 0;
	dis[u] = 0;
	while (u != dest) {
		vis[u] = true;
		int tempt, templ;
		for (i = 0; i<n; i++) {
			if (vis[i])continue;
			tempt = mapt[u][i] + tim[u];
			templ = mapl[u][i] + dis[u];
			if (tempt<tim[i]) {
				tim[i] = tempt;
				dis[i] = templ;
				pre[i] = u;
			}
			else if (tim[i] != MAX&&tempt == tim[i]) {
				if (templ<dis[i]) {
					dis[i] = templ;
					pre[i] = u;
				}
			}
		}
		tempt = MAX;
		for (i = 0; i<n; i++) {
			if (!vis[i] && tempt>tim[i]) {
				tempt = tim[i];
				u = i;
			}
		}
	}
}

void dijkstraForLength(int source, int dest) {
	init();
	int i;
	int u = source;
	tim[u] = 1;
	dis[u] = 0;
	while (u != dest) {
		vis[u] = true;
		int tempt, templ;
		for (i = 0; i<n; i++) {
			if (vis[i])continue;
			tempt = 1 + tim[u];
			templ = mapl[u][i] + dis[u];
			if (templ<dis[i]) {
				tim[i] = tempt;
				dis[i] = templ;
				pre[i] = u;
			}
			else if (dis[i] != MAX&&templ == dis[i]) {
				if (tempt<tim[i]) {
					tim[i] = tempt;
					pre[i] = u;
				}
			}
		}
		templ = MAX;
		for (i = 0; i<n; i++) {
			if (!vis[i] && templ>dis[i]) {
				templ = dis[i];
				u = i;
			}
		}
	}
}

void getroad(int source, int dest, stack<int>& citys, int* pre) {
	int u = dest;
	while (u != source) {
		citys.push(u);
		u = pre[u];
	}
	citys.push(source);
}

bool judge(stack<int> a, stack<int> b) {
	int len1 = a.size();
	int len2 = b.size();
	if (len1 != len2) return false;
	while (len1--) {
		if (a.top() != b.top()) return false;
		a.pop();
		b.pop();
	}
	return true;
}

int main() {
	int m;
	scanf("%d%d", &n, &m);
	int i;
	for (i = 0; i<n; i++)
		for (int j = 0; j<n; j++)
		{
			mapl[i][j] = MAX;
			mapt[i][j] = MAX;
		}
	int v1, v2, style, length, time;
	for (i = 0; i<m; i++) {
		scanf("%d%d%d%d%d", &v1, &v2, &style, &length, &time);
		mapl[v1][v2] = length;
		mapt[v1][v2] = time;
		if (!style) {
			mapl[v2][v1] = length;
			mapt[v2][v1] = time;
		}
	}
	int source, dest, mintime, mindis;
	scanf("%d%d", &source, &dest);
	dijkstraForTime(source, dest);
	mintime = tim[dest];
	stack<int> troad;
	getroad(source, dest, troad, pre);
	dijkstraForLength(source, dest);
	mindis = dis[dest];
	stack<int> lroad;
	getroad(source, dest, lroad, pre);
	if (judge(lroad, troad))
	{
		printf("Time = %d; Distance = %d: %d", mintime, mindis, lroad.top());
		lroad.pop();
		while (!lroad.empty()) {
			printf(" => %d", lroad.top());
			lroad.pop();
		}
	}
	else {
		printf("Time = %d: %d", mintime, troad.top());
		troad.pop();
		while (!troad.empty()) {
			printf(" => %d", troad.top());
			troad.pop();
		}
		printf("\n");
		printf("Distance = %d: %d", mindis, lroad.top());
		lroad.pop();
		while (!lroad.empty()) {
			printf(" => %d", lroad.top());
			lroad.pop();
		}
	}
	printf("\n");
	return 0;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值