最短路。
记录一下到某个点,最后是哪辆车乘到的最短距离、换乘次数以及从哪个位置推过来的,可以开$map$记录一下。
#include<map> #include<set> #include<ctime> #include<cmath> #include<queue> #include<string> #include<stack> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<functional> using namespace std; int n,A,B; map<int,int>dis; map<int,int>num; map<int,int>pre; map<int,bool>f; int a[200]; vector<int>g[10010]; struct X { int x,y,z; }s[1000010]; int sz; int xl[1000010],p; void add(int x,int y,int z) { s[sz].x=x; s[sz].y=y; s[sz].z=z; g[x].push_back(sz); sz++; } void SPFA() { dis.clear(); num.clear(); pre.clear(); f.clear(); queue<int>Q; for(int j=1;j<=n;j++) { dis[A*1000+j]=1; num[A*1000+j]=1; Q.push(A*1000+j); f[A*1000+j]=1; } while(!Q.empty()) { int h=Q.front(); Q.pop(); f[h]=0; int dian =h/1000 ,ban = h%1000; for(int i=0;i<g[dian].size();i++) { int id = g[dian][i]; int ha = s[id].y*1000+s[id].z; if(dis[ha]==0) { dis[ha] = dis[h]+1; if(s[id].z==ban) num[ha] = num[h]; else num[ha] = num[h]+1; pre[ha] = h; if(f[ha]==0) { f[ha]=1; Q.push(ha); } } else { if(dis[h]+1<dis[ha]) { dis[ha] = dis[h]+1; if(s[id].z==ban) num[ha] = num[h]; else num[ha] = num[h]+1; pre[ha] = h; if(f[ha]==0) { f[ha]=1; Q.push(ha); } } else if(dis[h]+1==dis[ha]) { int tmp; if(s[id].z==ban) tmp = num[h]; else tmp = num[h]+1; if(tmp<num[ha]) { dis[ha] = dis[h]+1; if(s[id].z==ban) num[ha] = num[h]; else num[ha] = num[h]+1; pre[ha] = h; if(f[ha]==0) { f[ha]=1; Q.push(ha); } } } } } } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { int m; scanf("%d",&m); for(int j=1;j<=m;j++) scanf("%d",&a[j]); for(int j=1;j<=m;j++) { if(j-1>=1) add(a[j],a[j-1],i); if(j+1<=m) add(a[j],a[j+1],i); } } int Q; scanf("%d",&Q); while(Q--) { scanf("%d%d",&A,&B); SPFA(); int ans=0x7FFFFFFF; for(int i=1;i<=n;i++) { if(dis[B*1000+i]==0) continue; ans=min(ans,dis[B*1000+i]-1); } printf("%d ",ans); int MinTra=0x7FFFFFFF,idx; for(int i=1;i<=n;i++) { if(dis[B*1000+i]-1!=ans) continue; if(num[B*1000+i]<MinTra) { MinTra=num[B*1000+i]; idx = B*1000+i; } } stack<int>st; int now =idx; while(1) { if(now==0) break; st.push(now); now = pre[now]; } p=0; while(!st.empty()) { xl[p++]=st.top(); st.pop(); } int len=p; xl[len]=0; p=0; while(1) { if(xl[p]%1000==xl[0]%1000) p++; else break; } p--; printf("Take Line#%d from %04d to %04d. ",xl[0]%1000,xl[0]/1000,xl[p]/1000); int pre = xl[p]/1000; while(1) { p++; if(p>len-1) break; int tmp = p; while(1) { if(xl[tmp]%1000==xl[p]%1000) p++; else break; } p--; printf("Take Line#%d from %04d to %04d. ",xl[p]%1000,pre,xl[p]/1000); pre=xl[p]/1000; } } return 0; }