本题未通过所有测试案例(22/30),希望有大佬能解答
本题链接:1131 Subway Map - PAT (Advanced Level) Practice (pintia.cn)
题意:
给一个地铁地图,求从一地到另一地如何乘车所经站最少,如有多条路线则找转乘次数少的那条路。
思路:
其实对于图论最优路径问题,不一定非要用Djikstra或者floyd算法,可以单纯的用一个dfs处理。
本题是多源求最短路径问题,本来想着是用floyd,但是本题为系数图·用矩阵存储特别不方便,因此采用邻接矩阵存储,用直接用dfs列举所有情况进行剪枝,重要的是注意需要回溯
代码:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int n;
const int N = 10010;
const int INF = 10000000000;
vector<vector<int>> mp;
int line[N][N];//用于记录该点在几号线上
int start, destination;
vector<int> temp, path;
int minStation = INF, minChange = INF;//用于存储最优情况
int nowStation = 0, nowChange = 0;//用于存储当前
bool vis[N];
void init() {
vector<int> a;
for (int i = 0; i < N; i++) {
mp.push_back(a);
}
fill(vis, vis + N, false);
}
void dfs(int now) {
//如果当前跑的太多还没到终点,直接return
if (nowStation > minStation) {
return;
}
if (now == destination) {
temp.push_back(now);
int nowSt = line[temp[0]][temp[1]];
nowChange = 1;
for (int i = 1; i < temp.size(); i++) {
if (line[temp[i - 1]][temp[i]] != nowSt) {
nowChange++;
nowSt = line[temp[i - 1]][temp[i]];
}
}
if (nowStation < minStation) {
minChange = nowChange;
minStation = nowStation;
if (path.size() > 0) path.clear();
for (int i = 0; i < temp.size(); i++) {
path.push_back(temp[i]);
}
}
else if (nowStation == minStation) {
if (nowChange < minChange) {
minChange = nowChange;
minStation = nowStation;
if (path.size() > 0) path.clear();
for (int i = 0; i < temp.size(); i++) {
path.push_back(temp[i]);
}
}
}
temp.pop_back();
return;
}
vis[now] = true;
nowStation++;
temp.push_back(now);
for (int i = 0; i < mp[now].size(); i++) {
if (!vis[mp[now][i]]) {
dfs(mp[now][i]);
}
}
nowStation--;
vis[now] = false;
temp.pop_back();
}
int main() {
init();
cin >> n;
for (int i = 1; i <= n; i++) {
int m;
cin >> m;
int now;
cin >> now;
for (int j = 0; j < m - 1; j++) {
int next;
cin >> next;
mp[now].push_back(next);
mp[next].push_back(now);
line[now][next] = i;
line[next][now] = i;
now = next;
}
}
int k;
cin >> k;
for (int i = 0; i < k; i++) {
path.clear();
temp.clear();
cin >> start >> destination;
nowStation = 0, nowChange = 1;
minStation = INF, minChange = INF;
dfs(start);
cout << minStation << endl;
if (minChange == 1) {
printf("Take Line#%d from %04d to %04d.\n",line[path[0]][path[1]], path[0], path[path.size() - 1]);
}
else {
int nLine = line[path[0]][path[1]];
int beginS = path[0];
int endS = path[0];
for (int kk = 1; kk < path.size(); kk++) {
if (line[path[kk - 1]][path[kk]] != nLine) {
printf("Take Line#%d from %04d to %04d.\n", nLine, beginS, endS);
nLine = line[path[kk - 1]][path[kk]];
beginS = path[kk-1];
}
else {
endS = path[kk];
}
}
printf("Take Line#%d from %04d to %04d.\n", nLine, beginS,path[path.size() - 1]);
}
}
return 0;
}