PAT 1131. Subway Map (30)

最短路。

记录一下到某个点,最后是哪辆车乘到的最短距离、换乘次数以及从哪个位置推过来的,可以开$map$记录一下。

#include<map>
#include<set>
#include<ctime>
#include<cmath>
#include<queue>
#include<string>
#include<stack>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;

int n,A,B;

map<int,int>dis;
map<int,int>num;
map<int,int>pre;
map<int,bool>f;
int a[200];
vector<int>g[10010];

struct X
{
    int x,y,z;
}s[1000010];
int sz;

int xl[1000010],p;

void add(int x,int y,int z)
{
    s[sz].x=x; s[sz].y=y; s[sz].z=z;
    g[x].push_back(sz); sz++;
}

void SPFA()
{
    dis.clear(); num.clear(); pre.clear(); f.clear();
    queue<int>Q;

    for(int j=1;j<=n;j++)
    {
        dis[A*1000+j]=1;
        num[A*1000+j]=1;
        Q.push(A*1000+j); f[A*1000+j]=1;
    }

    while(!Q.empty())
    {
        int h=Q.front(); Q.pop(); f[h]=0;
        int dian =h/1000 ,ban = h%1000;
        for(int i=0;i<g[dian].size();i++)
        {
            int id = g[dian][i];
            int ha = s[id].y*1000+s[id].z;

            if(dis[ha]==0)
            {
                dis[ha] = dis[h]+1;
                if(s[id].z==ban) num[ha] = num[h];
                else num[ha] = num[h]+1;
                pre[ha] = h;
                if(f[ha]==0) { f[ha]=1; Q.push(ha); }
            }
            else
            {
                if(dis[h]+1<dis[ha])
                {
                    dis[ha] = dis[h]+1;
                    if(s[id].z==ban) num[ha] = num[h];
                    else num[ha] = num[h]+1;
                    pre[ha] = h;
                    if(f[ha]==0) { f[ha]=1; Q.push(ha); }
                }

                else if(dis[h]+1==dis[ha])
                {
                    int tmp;
                    if(s[id].z==ban) tmp = num[h];
                    else tmp = num[h]+1;

                    if(tmp<num[ha])
                    {
                        dis[ha] = dis[h]+1;
                        if(s[id].z==ban) num[ha] = num[h];
                        else num[ha] = num[h]+1;
                        pre[ha] = h;
                        if(f[ha]==0) { f[ha]=1; Q.push(ha); }
                    }
                }
            }
        }
    }
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        int m; scanf("%d",&m);
        for(int j=1;j<=m;j++) scanf("%d",&a[j]);
        for(int j=1;j<=m;j++)
        {
            if(j-1>=1) add(a[j],a[j-1],i);
            if(j+1<=m) add(a[j],a[j+1],i);
        }
    }

    int Q; scanf("%d",&Q);
    while(Q--)
    {
        scanf("%d%d",&A,&B);
        SPFA();

        int ans=0x7FFFFFFF;
        for(int i=1;i<=n;i++)
        {
            if(dis[B*1000+i]==0) continue;
            ans=min(ans,dis[B*1000+i]-1);
        }

        printf("%d\n",ans);

        int MinTra=0x7FFFFFFF,idx;
        for(int i=1;i<=n;i++)
        {
            if(dis[B*1000+i]-1!=ans) continue;
            if(num[B*1000+i]<MinTra)
            {
                MinTra=num[B*1000+i];
                idx = B*1000+i;
            }
        }

        stack<int>st; int now =idx;
        while(1)
        {
            if(now==0) break;
            st.push(now);
            now = pre[now];
        }

        p=0;
        while(!st.empty()) { xl[p++]=st.top(); st.pop(); }

        int len=p; xl[len]=0;


        p=0;
        while(1)
        {
            if(xl[p]%1000==xl[0]%1000) p++;
            else break;
        }
        p--;

        printf("Take Line#%d from %04d to %04d.\n",xl[0]%1000,xl[0]/1000,xl[p]/1000);

        int pre = xl[p]/1000;
        while(1)
        {
            p++; if(p>len-1) break;
            int tmp = p;
            while(1)
            {
                if(xl[tmp]%1000==xl[p]%1000) p++;
                else break;
            }
            p--;
            printf("Take Line#%d from %04d to %04d.\n",xl[p]%1000,pre,xl[p]/1000);
            pre=xl[p]/1000;
        }

    }
    return 0;
}

 

posted @ 2017-03-23 09:47  Fighting_Heart  阅读(1036)  评论(0编辑  收藏  举报