/*************************
题意:
一个特殊的地铁图
求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;
}