1131 Subway Map

题目

题意: 找出一条路线,使得对任何给定的起点和终点,可以找出中途经停站最少的路线;如果经停站一样多,则取需要换乘线路次数最少的路线

tip:DFS + map

分析:0.可以这样计算出一条线路的换乘次数:在line[10000][10000]的数组中保存每两个相邻站中间的线路是几号线~从头到尾遍历最终保存的路径,preLine为前一小段的线路编号,如果当前的结点和前一个结点组成的这条路的线路编号和preLine不同,说明有一个换乘,就将cnt+1,最后遍历完累加的cnt即是换乘的次数~1.可以这样计算出一条线路中途停站的次数:在dfs的时候有个变量cnt,表示当前路线是所需乘的第几个站,每次dfs时候将cnt+1表示向下遍历一层~cnt就是当前中途停站的次数~2.可以这样输出结果:和计算线路换乘次数的思路一样,每当preLine和当前Line值不同的时候就输出一句话~保存preTransfer表示上一个换乘站,最后不要忘记输出preTransfer和最后一个站之间的路即使最后一个站并不是换乘站

#include<iostream>
#include<vector>
#include<cstring>
#include<unordered_map>
using namespace std;
vector<int> s[10003];
int checked[10003]= {0};
int mincnt,mintransfer,ed;
unordered_map<int,int>line;
vector<int>path,temp;
int getcnt(vector<int> a) {//计算换乘数
	int cnt=-1,preline=0;
	for(int i=1; i<a.size(); ++i) {
		if(line[a[i-1]*10000+a[i]]!=preline)
			cnt++;
		preline=line[a[i-1]*10000+a[i]];
	}
	return cnt;
}
void dfs(int start,int cnt) {
	temp.push_back(start);
	checked[start]=1;
	if(cnt>mincnt)
		return ;
	if(start==ed) {
		if(cnt==mincnt) {//站数相同比较换乘数
			if(getcnt(temp)<mintransfer) {
				path=temp;
				mintransfer=getcnt(temp);
			}
		} else  {
			path=temp;
			mincnt=cnt;
			mintransfer=getcnt(temp);
		}
		return ;
	}
	for(auto i : s[start]) {
		if(checked[i]==0) {
			dfs(i,cnt+1);
			temp.pop_back();
			checked[i]=0;
		}
	}
}
int main() {
	int n;
	cin>>n;
	for(int i=0; i<n; ++i) {
		int m,prestation,tempstation;
		cin>>m>>prestation;
		for(int j=1; j<m; ++j) {
			cin>>tempstation;
			s[prestation].push_back(tempstation);
			s[tempstation].push_back(prestation);
			line[prestation*10000+tempstation]=line[tempstation*10000+prestation]=i+1;//每记录两个站之间的地铁号
			prestation=tempstation;
		}
	}
	int k;
	cin>>k;
	for(int i=0; i<k; ++i) {
		int a;
		cin>>a>>ed;
		mincnt=1e7;
		mintransfer=1e7;
		memset(checked,0,sizeof(checked));
		temp.clear();
		dfs(a,0);
		cout<<mincnt<<endl;
		int preline=0,pretransfer=a;
		for(int j=1; j<path.size(); ++j) {
			if(line[path[j-1]*10000+path[j]]!=preline) {//与前一站地铁号不同就得换乘
				if(preline)
					printf("Take Line#%d from %04d to %04d.\n", preline, pretransfer, path[j-1]);
				preline = line[path[j-1]*10000+path[j]];
				pretransfer = path[j-1];
			}
		}
		printf("Take Line#%d from %04d to %04d.\n", preline, pretransfer, ed);
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章