天梯赛 周游世界

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();
    }
}

 

posted @ 2020-10-04 12:55  TRTTG  阅读(247)  评论(0编辑  收藏  举报