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;
}

 

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