本质是个dijkstra的裸题,但是特别的烦。。。。
由于图很复杂,所以不要一开始就将所有可相互到达的点连边,而是在dijkstra跑的时候,查询bus路线,再连边。
然后压入优先队列的时候,以及弹出的时候,要判断下是否比当前最优解差,是的话就continue。
因为要输出路径,所以还要存from节点。
总之,特别的烦。。。
#include <bits/stdc++.h>
using namespace std;
const int MAXN=10010;
const int MAXM=110;
int s[MAXM][MAXM];
int dis[MAXN],cha[MAXN],from[MAXN],take[MAXN],ansfrom[MAXN],ansto[MAXN],ansbus[MAXN];
vector<int> can_bus[MAXN],stop_num[MAXN];
struct node
{
int x,dis,cha,from,take;
bool friend operator <(node n1,node n2)
{
if(n1.dis!=n2.dis)
return n1.dis>n2.dis;
return n1.cha>n2.cha;
}
}now,son;
priority_queue <node> q;
int main()
{
int n,i,j,qnum,st,ed,busindex,stopindex,ansdis,chanum,nowx;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&s[i][0]);
for(j=1;j<=s[i][0];j++)
{
scanf("%d",&s[i][j]);
can_bus[s[i][j]].push_back(i);
stop_num[s[i][j]].push_back(j);
}
}
scanf("%d",&qnum);
while(qnum--)
{
scanf("%d%d",&st,&ed);
memset(dis,-1,sizeof(dis));
while(!q.empty())
q.pop();
now.x=st; now.dis=0; now.cha=0; now.from=-1; now.take=-1;
q.push(now);
ansdis=-1;
while(!q.empty())
{
now=q.top();
q.pop();\
if(dis[now.x]!=-1&&dis[now.x]<now.dis||(dis[now.x]==now.dis&&cha[now.x]<now.cha))
continue;
dis[now.x]=now.dis;
cha[now.x]=now.cha;
from[now.x]=now.from;
take[now.x]=now.take;
if(now.x==ed)
{
ansdis=now.dis;
break;
}
for(i=0;i<can_bus[now.x].size();i++)
{
busindex=can_bus[now.x][i];
stopindex=stop_num[now.x][i];
for(j=1;j<=s[busindex][0];j++)
{
son.x=s[busindex][j];
son.dis=now.dis+abs(stopindex-j);
son.cha=now.cha+1;
son.from=now.x;
son.take=busindex;
if(dis[son.x]!=-1&&dis[son.x]<son.dis||(dis[son.x]==son.dis&&cha[son.x]<son.cha))
continue;
dis[son.x]=son.dis;
cha[son.x]=son.cha;
q.push(son);
}
}
}
if(ansdis!=-1)
{
chanum=0;
nowx=ed;
while(nowx!=-1)
{
ansto[chanum]=nowx;
ansfrom[chanum]=from[nowx];
ansbus[chanum]=take[nowx];
nowx=from[nowx];
chanum++;
}
printf("%d\n",ansdis);
for(i=chanum-2;i>=0;i--)
{
printf("Go by the line of company #%d from %04d to %04d.\n",ansbus[i],ansfrom[i],ansto[i]);
}
}
else
printf("Sorry, no line is available.\n");
}
}