天梯赛 周游世界
https://pintia.cn/problem-sets/994805046380707840/problems/994805048482054144
就是求从s到t在满足2个条件下的最短路
条件1:经过边数最少
条件2:在条件1的基础上换乘次数最少
条件1好满足,直接bfs一遍,记录边数即可
条件2,因为题目说换乘点不会超过5条边,所以在每个换乘点都记录一下在最短路和换乘次数最少的前提下,该点是由哪几种边到达的
输出方案的时候
从终点开始往前走
假设一条从u到v的边
首先要满足到u的最短路比到v的最短路少1
对于条件2,如果u和v的最少换乘次数一样,那么在到u的前面说的记录的边里,一定有一条和当前边同一类型的边
如果u比v的换乘次数少一次,那么u就是到v之前经过的点
#include<cstdio> #include<queue> #include<cstring> using namespace std; #define N 100001 int front[N],to[N<<1],nxt[N<<1],tot,col[N<<1]; int s,d; int dis[N],chan[N],wh[N][6]; bool in[N]; int ansp[N],ansc[N]; void add(int u,int v,int w) { to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; col[tot]=w; } void solve() { for(int i=0;i<N;++i) { dis[i]=1e9; chan[i]=1e9; wh[i][0]=0; } memset(in,false,sizeof(in)); queue<int>q; dis[s]=chan[s]=0; q.push(s); in[s]=true; int now,t,tmp; while(!q.empty()) { now=q.front(); q.pop(); in[now]=false; for(int i=front[now];i;i=nxt[i]) { t=to[i]; if(dis[t]>=dis[now]+1) { if(dis[t]>dis[now]+1) { dis[t]=dis[now]+1; tmp=chan[now]; int j; for(j=1;j<=wh[now][0];++j) if(col[i]==wh[now][j]) break; if(j>wh[now][0]) tmp++; wh[t][0]=1; wh[t][1]=col[i]; chan[t]=tmp; } else { tmp=chan[now]; int j; for(j=1;j<=wh[now][0];++j) if(col[i]==wh[now][j]) break; if(j>wh[now][0]) tmp++; if(tmp<chan[t]) { chan[t]=tmp; wh[t][0]=1; wh[t][1]=col[i]; } else if(tmp==chan[t]) { bool ii=false; for(int k=1;k<=wh[t][0] && !ii;++k) if(wh[t][k]==col[i]) ii=true; if(!ii) { wh[t][0]++; wh[t][wh[t][0]]=col[i]; } } else continue; } } else continue; if(!in[t] && t!=d) { q.push(t); in[t]=true; } } } if(dis[d]==1e9) printf("Sorry, no line is available.\n"); else { printf("%d\n",dis[d]); now=d; int sum=0; bool flag; ansp[++sum]=d; while(now!=s) { for(int i=front[now];i;i=nxt[i]) if(dis[to[i]]==dis[now]-1) { if(chan[to[i]]==chan[now]) { flag=false; for(int j=1;j<=wh[to[i]][0] && !flag;++j) if(wh[to[i]][j]==col[i]) flag=true; if(flag) { now=to[i]; break; } } else if(chan[to[i]]==chan[now]-1) { ansc[sum]=col[i]; ansp[++sum]=to[i]; now=to[i]; break; } } } for(int i=sum-1;i;--i) printf("Go by the line of company #%d from %04d to %04d.\n",ansc[i],ansp[i+1],ansp[i]); } } int main() { int T,m,x,last; scanf("%d",&T); for(int i=1;i<=T;++i) { scanf("%d",&m); scanf("%d",&last); while(--m) { scanf("%d",&x); add(last,x,i); add(x,last,i); last=x; } } scanf("%d",&T); while(T--) { scanf("%d%d",&s,&d); solve(); } }