PAT 甲级 1131 Subway Map (30 分)

思路:

1.将每站的邻站和与邻站在哪条地铁线记录下来;
2.bfs,搜索距离最近的站台,如果搜索到终点站且距离相等的站台搜索完毕即break;
3.用数组记录此站台是否被访问过,如果此站台被访问且它不是换乘站也不是终点站那就跳过它;
4.如果被访问的站台已经被访问过且它是终点站,我们需要注意比较换乘次数;
5.如果被访问的站台已经被访问且它是换乘站,我们不仅需要比较历史换乘次数,还要考虑往下一站是否需要换乘,不需要换乘的线路优先;

代码:

#include<iostream>
#include<queue>
#include<vector>
#include<unordered_map>
using namespace std;
int lnno[10000][10000];
unordered_map<int,vector<int>> mp;
struct node{
	int path,dist,tnf;
};
unordered_map<int,node> nds;
void print(int end,int last,int now){
	if(now==nds[now].path){
		printf("Take Line#%d from %04d to %04d.\n",lnno[last][now],now,end);
		return;
	}
	if(last!=now&&lnno[last][now]!=lnno[now][nds[now].path]){
		print(now,now,nds[now].path);
		printf("Take Line#%d from %04d to %04d.\n",lnno[last][now],now,end);
	}
	else print(end,now,nds[now].path);
}
int main(){
	int n,m,k;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&k);
		vector<int> sta(k);
		for(int j=0;j<k;j++) scanf("%d",&sta[j]);
		for(int j=0;j<k;j++){
			if(j>0){
				mp[sta[j]].push_back(sta[j-1]);
				lnno[sta[j]][sta[j-1]]=i;
			}
			if(j<k-1){
				mp[sta[j]].push_back(sta[j+1]);
				lnno[sta[j]][sta[j+1]]=i;
			}
		}
	}
	scanf("%d",&k);
	for(int i=0;i<k;i++){
		int start,end;
		scanf("%d%d",&start,&end);
		unordered_map<int,int> isv;
		nds.clear();
		queue<int> q;
		q.push(start);
		isv[start]=1;
		nds[start]={start,0,0}; 
		for(int d=0,flag=0;!q.empty();q.pop()){
			int f=q.front();
			if(flag&&d<nds[f].dist) break;
			for(auto e:mp[f]){
				if(isv[e]==0) q.push(e);
				if(e==end) flag=1;
				int t=lnno[f][nds[f].path]==lnno[f][e]?nds[f].tnf:nds[f].tnf+1;
				if(isv[e]++==0||(nds[e].dist==nds[f].dist+1&&nds[e].tnf>=t)) nds[e]={f,nds[f].dist+1,t};
			}
			d=nds[f].dist;
		}
		printf("%d\n",nds[end].dist);
		print(end,end,end);
	}
	return 0;
}
posted @ 2019-08-22 15:44  YuhanのBlog  阅读(65)  评论(0编辑  收藏  举报