#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
const int N=10010,M=1000010;
int h[N],e[M],ne[M],w[M],line[M];
string s[N];
int dist[N],st[N],pre[N],cnt[N],idx;
int n,m,ss,ee;
void add(int a,int b,int c,int d)
{
e[idx]=b,w[idx]=c,line[idx]=d,ne[idx]=h[a],h[a]=idx++;
}
string to_s(int x)
{
string s=to_string(x),ss="";
for(int i=0;i<4-s.size();i++)ss+="0";
return ss+s;
}
void dijk(int ss,int ee)
{
memset(dist,0x3f,sizeof dist);
memset(st,0,sizeof st);
memset(cnt,0x3f,sizeof cnt);
dist[ss]=cnt[ss]=0;
priority_queue<pii,vector<pii>,greater<pii>>q;
q.push({0,ss});
while(q.size())
{
auto t=q.top();
q.pop();
int ver=t.second;
if(ver==ee)break;
for(int i=h[ver];i!=-1;i=ne[i])
{
int j=e[i];
if(dist[j]>dist[ver]+w[i])
{
cnt[j]=cnt[ver];
dist[j]=dist[ver]+w[i];
pre[j]=ver;
q.push({dist[j],j});
// cout<<to_s(j)<<"++"<<endl;
s[j]="Take Line#"+to_string(line[i])+" from "+to_s(ver)+" to "+to_s(j)+".";
}else if(dist[j]==dist[ver]+w[i])
{
if(cnt[j]>cnt[ver]+1)
{
cnt[j]=cnt[ver]+1;
pre[j]=ver;
s[j]="Take Line#"+to_string(line[i])+" from "+to_s(ver)+" to "+to_s(j)+".";
}
}
}
}
}
void print(int x)
{
if(x!=ss)print(pre[x]);
else return;
cout<<s[x]<<endl;
}
int main()
{
cin>>n;
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
memset(h,-1,sizeof h);
for(int i=1;i<=n;i++)
{
vector<int>g;
int x;
cin>>x;
for(int j=0;j<x;j++)
{
int y;
cin>>y;
g.push_back(y);
}
for(int j=0;j<x;j++)
{
for(int k=0;k<j;k++)
{
int len=0;
if(g[0]!=g[x-1])len=j-k;
else len=min(j-k,x-1-j+k);
// cout<<g[j]<<" "<<g[k]<<" "<<len<<endl;
add(g[j],g[k],len,i);
add(g[k],g[j],len,i);
}
}
}
int k;
cin>>k;
while(k--)
{
cin>>ss>>ee;
dijk(ss,ee);
cout<<dist[ee]<<endl;
print(ee);
}
}
该题是最短路算法,其中建图的时候,因为题目中说可能会有环,但是不会有自环,如果没有环,那一条地铁线之间的距离就是两个下标之差,如果有环,那就要考虑取最近的距离最为两点之间的距离, 最后的答案还要输出路线,我们可以在更新前驱节点的同时更新路线,最后就和以前的题一眼,直接递归输出即可。