考试的时候这道题写了超久……中间推翻了一开始直连相邻边的想法 改成全部连边 总算过了……没有白费考前狂练多关键字最短路的成果……然而 物理题没做出来 拖后腿了。
大概思路嘛,姥姥出的题,肯定是多关键字最短路233 然后我一开始是相邻连边,但是后来发现一个路径不好记录,而且点数什么的也不好设置,无法转化。后来才发现完全
可以同一条线路全部连边,有重边的话 最短路算法是不影响的。(想到了以前某场CF gym里的题) 然后就想到了 记录路径也不难了。。然后终于A了QAQ 其实floyed应该也够了…… 我用了dijkstra。。。
#include<bits/stdc++.h>
using namespace std;
const int maxn=100010;
const int inf=(1<<30)-1;
int n;
set<int> s[maxn];
int m,a[maxn];
map<string,int> m1;
map<int,string> m2;
struct data{
int to,v,w;
};
vector<data> G[maxn];
int d[maxn],vis[maxn];
int path[maxn];
int num[maxn];
int pp[maxn];
int tot=0;
struct node{
int u,d,num;
bool operator <(const node &b) const {
return (d==b.d)?num>b.num:d>b.d;
}
};
void dij(int s)
{
priority_queue<node> q;
for(int i=0;i<=maxn-1;i++) d[i]=inf;
memset(vis,0,sizeof(vis));
d[s]=0;
memset(path,0,sizeof(path));
memset(pp,0,sizeof(pp));
path[s]=-1;
num[s]=1;
q.push((node){s,d[s],num[s]});
while(!q.empty())
{
node x=q.top();q.pop();
int u=x.u;
if(vis[u]) continue;
vis[u]=1;
for(int i=0;i<G[u].size();i++)
{
data &e=G[u][i];
int to=e.to,v=e.v,w=e.w;
//printf("%d %d\n",to,v);
if(d[to]>d[u]+v)
{
d[to]=d[u]+v;
num[to]=num[u]+1;
q.push((node){to,d[to],num[to]});
path[to]=u;
//printf("%d %d %d %d\n",u,to,num[u],num[to]);
pp[to]=w;
}
else if(d[to]==d[u]+v)
{
if(num[to]>num[u]+1)
{
num[to]=num[u]+1;
q.push((node){to,d[to],num[to]});
path[to]=u;
pp[to]=w;
}
}
}
}
}
void dfs(int x)
{
if(path[x]==-1) return;
dfs(path[x]);
cout<<"Go by the line of company #"<<pp[x]<<" from "<<m2[path[x]]<<" to "<<m2[x]<<"."<<endl;
}
int main()
{
scanf("%d",&n);
for(int k=1;k<=n;k++)
{
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
string str;
cin>>str;
if(!m1[str]) m1[str]=++tot,m2[m1[str]]=str;a[i]=m1[str];
}
for(int i=1;i<=m;i++)
for(int j=1;j<i;j++)
{
int x=a[i],y=a[j];
G[x].push_back((data){y,i-j,k});
G[y].push_back((data){x,i-j,k});
}
}
int Q;
scanf("%d",&Q);
while(Q--)
{
string s1,s2;
cin>>s1>>s2;
int x=m1[s1],y=m1[s2];
dij(x);
if(d[y]!=inf)printf("%d\n",d[y]),dfs(y);
else puts("Sorry, no line is available.");
}
return 0;
}