1. 程式人生 > >PAT 1131. Subway Map (30) 地鐵換乘,優先BFS搜圖應用

PAT 1131. Subway Map (30) 地鐵換乘,優先BFS搜圖應用

/*************************
題意:
一個特殊的地鐵圖
求s到e的最短距離路線
如果距離相同,求換乘次數最少的路線
************************/
/***********************
解題思路:
由於點可能有10000個,用dijkstr容易超時
而這裡的特點是隻有100條地鐵站,每個點最多5個度
即有很多情況是隻有1個選擇的情況(筆直向下走)
因此,我們選擇使用BFS,能充分利用這個特性。

儲存圖是要把邊也存進去,為了判斷是否換乘,我們是利用邊的組id去判斷的。

入隊的是行進狀態State
	該狀態包括當前站,當前線路組id,當前行進距離,和當前換乘距離
然後利用優先佇列去做佇列
因為結果不唯一,所以我們可以設定一個vis[],已經出隊的點,就設定vis=1
接下來這個點不需要再入隊。
處理要怎麼計算換乘和儲存換乘節點即可。
*************************/
/***********************
注意:
	優先bfs時,注意vis只在入隊時判斷,只在出隊時去設1
*********************/
#include<iostream>
#include<stdio.h>
#include<string>
#include<vector>
#include<queue>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<stack>
#include<map>
#include<set>
#include<unordered_map>
using namespace std;
#define M 10005
#define INF 0x7ffffff

vector<int> edg[M];
struct Road{
	int s;
	int e;
	int id;
};
Road road[M];

struct State{
	int dis;
	int cnum; //change num
	int nowcity;
	int nowroad;
	vector<int> cv;
	vector<int> rv;
    bool operator < (const State & a) const{
		if(dis > a.dis)
			return true;
		else if(dis == a.dis)
			return cnum > a.cnum;
		else return false;
    }
};
int vis[M];
void dijk(int start,int end){
	int i;
	priority_queue<State> q;
	memset(vis,0,sizeof(vis));
	State sta;
	sta.cnum = 0;
	sta.nowcity = start;
	sta.dis = 0;
	sta.nowroad = -1;
	q.push(sta);
	int city;
	Road r;
	int e;
	State pushs;
	while(!q.empty()){
		sta = q.top();
		q.pop();
		city = sta.nowcity;
		vis[city] = 1;
		if(city == end){
			int lastc;
			sta.cv.push_back(end);
			cout<<sta.dis<<endl;
			for(i = 0;i < sta.rv.size();i++){
				printf("Take Line#%d from %04d to %04d.\n",sta.rv[i],sta.cv[i],sta.cv[i+1]);
			}
			break;
		}
		for(i = 0;i < edg[city].size();i++){
			pushs = sta;
			r = road[edg[city][i]];
			if(r.s == city)
				e = r.e;
			else e = r.s;

			if(vis[e])
				continue;
			if(r.id != sta.nowroad){
				pushs.cnum++;
				pushs.cv.push_back(sta.nowcity); //將變換處的起點放入
				pushs.rv.push_back(r.id);
				pushs.nowroad = r.id;
			}
			pushs.dis++;
			pushs.nowcity = e;
			q.push(pushs);
		}
	}
}



int main(){
	int n, i, m, k;
	int j,node,lastnode;
	scanf("%d",&n);

	j=0;
	for(i = 1;i <= n;i++){
		scanf("%d",&k);
		lastnode = -1;
		while(k--){
			scanf("%d",&node);
			if(lastnode != -1){
				edg[lastnode].push_back(j);
				edg[node].push_back(j);
				road[j].s = lastnode;
				road[j].e = node;
				road[j].id = i;
				j++;
			}
			lastnode = node;
		}
	}	
	cin>>k;
	int s, e;
	while(k--){
		cin>>s>>e;
		dijk(s,e);
	}

	return 0;
}