PAT 1131. Subway Map (30) 地鐵換乘,優先BFS搜圖應用
阿新 • • 發佈:2019-02-18
/************************* 題意: 一個特殊的地鐵圖 求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; }