PAT甲级刷题之路——A1131 Subway Map


既然是地铁图,那8成是图论题了(我为啥每次都在看题前立flag,orz

原题如下

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

题目大意

给出用户的始发地和终点,找出最近的路线。
输入:
第一行是整数N表示地铁路线数,然后接下来N行代表第i行的地铁线的格式:
M S[1] S[2] … S[M]
其中M表示站点,S[i]表示站点的标号,站名用4个数字表示
S[i]-S[i+1]之间没有站点
提示:可能有循环,但没有自循环,没有站点可以路经5条线。
然后紧接着是K:case数
接下来K行描述每个用户的始发站和终点站
输出:
首先输出最短路线的站点数。
然后输出格式如下:
在这里插入图片描述
提示:除了始发站和终点站只需输出中转站。
如果最短路线不唯一,则输出最少中转站的路线。

自己的想法

是一道有多尺度的dijkstra问题,一个指标是站点数,一个指标是中转站数,两个指标即可完成这道题。
无向图!
后来忘了自己用dij怎么做的了,于是转用dsp了

技巧总结

技巧1:解决内存超限

由于line[10000][10000]太大了,内存会超限,所以需要改进,因为题目每个站点标号都是四位组成的,所以可以将两站合并成一个int型的然后储存进unorder_map<int,int> line,第一个int储存a[i-1]*10000+a[i],第二个储存a[i-1]到a[i]间的地铁线路.

错误总结

dsp的判别中我出错了,错误为:

if (st == ed && rode < minrode&&transfer(vec) < stops) {
		minrode = rode; stops = transfer(vec); ans = vec;
	}

其中当道路更近时没必要满足转站更少的要求,所以需要写为:

if (st == ed && (rode < minrode||(rode==minrode&&transfer(vec) < stops))) {
		minrode = rode; stops = transfer(vec); ans = vec;
	}

AC代码

#include<iostream>
#include<cstdio>
#include<string>
#include<cctype>
#include<cstring>
//#include<stdlib>
#include<algorithm>
#include<ctime>
#include<cmath>
#include<vector>
#include<cstdlib>
#include<set>
#include<queue>
#include<map>
#include<stack>
#include<unordered_map>
using namespace std;
unordered_map<int, int> rode;
int minrode = 1000000, stops = 1000000;
vector<int> vec, ans;
bool flag[10000] = { false };
vector<int> child[10000];
int transfer(vector<int> vc) {
	int preline = -1;
	int pose = -1;
	int len = vc.size();
	for (int i = 1; i < len; i++) {
		int st = vc[i - 1], ed = vc[i];
		if (preline != rode[st * 10000 + ed]) {
			pose++; preline = rode[st * 10000 + ed];
		}
	}
	return pose;
}
void dsp(int st, int ed, int rode) {
	if (st == ed && (rode < minrode||(rode==minrode&&transfer(vec) < stops))) {
		minrode = rode; stops = transfer(vec); ans = vec;
	}
	if (st == ed)return;
	else {
		int len = child[st].size();
		for (int i = 0; i < len; i++) {
			if (flag[child[st][i]] == false) {
				flag[child[st][i]] = true;
				vec.push_back(child[st][i]);
				dsp(child[st][i], ed, rode + 1);
				vec.pop_back();
				flag[child[st][i]] = false;
			}
		}
	}
}
int main() {
#ifdef testing
	freopen("input.txt", "r", stdin);
#endif
	int n, m;
	cin >> n;
	//cout << "n=" << n << endl;
	for (int i = 1; i <= n; i++) {
		cin >> m;
		//cout << "m=" << m << endl;
		int temp;
		cin >> temp;
		for (int j = 1; j < m; j++) {
			int ed;
			cin >> ed;
			int dist = temp * 10000 + ed;
			rode[dist] = i;
			rode[ed * 10000 + temp] = i;
			child[temp].push_back(ed);
			child[ed].push_back(temp);
			temp = ed;
		}
	}
	int k;
	cin >> k;
	//cout << k << endl;
	for (int i = 0; i < k; i++) {
		int start, end;
		cin >> start >> end;
		vec.clear();
		vec.push_back(start);
		flag[start] = true;
		minrode = 1000000; stops = 1000000;
		//cout << '-' << endl;
		dsp(start, end, 0);
		//cout << '-' << endl;
		flag[start] = false;
		printf("%d\n", minrode);
		int len = ans.size();
		int preline = rode[ans[0]*10000+ans[1]];
		printf("Take Line#%d from %04d to", rode[ans[0]*10000+ans[1]], start);
		for (int j = 1; j < len-1; j++) {
			//cout << rode[ans[j] * 10000 + ans[j + 1]] << ' ' << preline << endl;
			if (rode[ans[j] * 10000 + ans[j+1]] != preline) {
				printf(" %04d.\n", ans[j]);
				printf("Take Line#%d from %04d to", rode[ans[j] * 10000 + ans[j + 1]], ans[j]);
			}
			preline = rode[ans[j] * 10000 + ans[j+1]];
		}
		printf(" %04d.\n", ans[len - 1]);
	}
	return 0;
}

结语

临时抱佛脚哈哈

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值