既然是地铁图,那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;
}
结语
临时抱佛脚哈哈