最短路PTA

来源:互联网 发布:乐视线刷软件 编辑:程序博客网 时间:2024/06/05 14:36

题目链接:https://pintia.cn/problem-sets/905631457273864192/problems/905631519127265289


题意:

本题要求你实现一个天梯赛专属在线地图,队员输入自己学校所在地和赛场地点后,该地图应该推荐两条路线:一条是最快到达路线;一条是最短距离的路线。题目保证对任意的查询请求,地图上都至少存在一条可达路线。

输入格式:

输入在第一行给出两个正整数N(2  N  500)和M,分别为地图中所有标记地点的个数和连接地点的道路条数。随后M行,每行按如下格式给出一条道路的信息:

V1 V2 one-way length time

其中V1V2是道路的两个端点的编号(从0到N-1);如果该道路是从V1V2的单行线,则one-way为1,否则为0;length是道路的长度;time是通过该路所需要的时间。最后给出一对起点和终点的编号。

输出格式:

首先按下列格式输出最快到达的时间T和用节点编号表示的路线:

Time = T: 起点 => 节点1 => ... => 终点

然后在下一行按下列格式输出最短距离D和用节点编号表示的路线:

Distance = D: 起点 => 节点1 => ... => 终点

如果最快到达路线不唯一,则输出几条最快路线中最短的那条,题目保证这条路线是唯一的。而如果最短距离的路线不唯一,则输出途径节点数最少的那条,题目保证这条路线是唯一的。

如果这两条路线是完全一样的,则按下列格式输出:

Time = T; Distance = D: 起点 => 节点1 => ... => 终点

输入样例1:

10 150 1 0 1 18 0 0 1 14 8 1 1 15 4 0 2 35 9 1 1 40 6 0 1 17 3 1 1 28 3 1 1 22 5 0 2 22 1 1 1 11 5 0 1 31 4 0 1 19 7 1 1 33 1 0 2 56 3 1 2 15 3

输出样例1:

Time = 6: 5 => 4 => 8 => 3Distance = 3: 5 => 1 => 3

输入样例2:

7 90 4 1 1 11 6 1 3 12 6 1 1 12 5 1 2 23 0 0 1 13 1 1 3 13 2 1 2 14 5 0 2 26 5 1 2 13 5

输出样例2:

Time = 3; Distance = 4: 3 => 2 => 5

代码:(迪杰斯特拉实现)


#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <string>#include <algorithm>#include <set>#include<malloc.h>#include <map>#include <vector>#include <stack>#include <queue>#define ri(n) scanf("%d",&n)#define oi(n) printf("%d\n",n)#define rl(n) scanf("%lld",&n)#define ol(n) printf("%lld\n",n)#define rep(i,l,r) for(i=l;i<=r;i++)#define rep1(i,l,r) for(i=l;i<r;i++)using namespace std;typedef long long ll;const int inf=0x3f3f3f3f;const int epg=10-8;const int maxn=1000;int n,m,S,D;//顶点数,边数int e[maxn][maxn],e2[maxn][maxn];int vis[maxn],d[maxn],pathcount[maxn],path[maxn],ren[maxn],acount[maxn],v[maxn],v2[maxn],pathd[maxn];void dijiesi1(int s,int t){    for(int i=0; i<maxn; i++)    {        d[i]=inf;        vis[i]=0;        pathcount[i]=0;//在确保最短路的时候确保结点数最少        path[i]=-1;//记录路径    }    d[s]=0;    while(1)    {        int v=-1;        for(int i=0; i<n; i++)        {            if(!vis[i]&&(v==-1||d[i]<d[v]))                v=i;        }        if(v==-1)            break;        vis[v]=1;        for(int i=0; i<n; i++)        {            if(!vis[i])            {                if(d[i]>d[v]+e[v][i])                {                    d[i]=d[v]+e[v][i];                    path[i]=v;                    pathcount[i]=pathcount[v]+1;//更新节点数                }                else if(d[i]==d[v]+e[v][i])//路长一样                {                    if(pathcount[i]>pathcount[v]+1)                    {                        pathcount[i]=pathcount[v]+1;//则取节点数少的那条边                        path[i]=v;                    }                }            }        }    }}void dijiesi2(int s,int t){    for(int i=0; i<maxn; i++)    {        d[i]=inf;        vis[i]=0;        pathd[i]=0;//时间最快确保路径最短        path[i]=-1;    }    d[s]=0;    while(1)    {        int v=-1;        for(int i=0; i<n; i++)        {            if(!vis[i]&&(v==-1||d[i]<d[v]))                v=i;        }        if(v==-1)            break;        vis[v]=1;        for(int i=0; i<n; i++)        {            if(!vis[i])            {                if(d[i]>d[v]+e2[v][i])                {                    d[i]=d[v]+e2[v][i];                    path[i]=v;         //记录路径                    pathd[i]=pathd[v]+e[v][i];     //更新路径长度                }                else if(d[i]==d[v]+e2[v][i])                {                    if(pathd[i]>pathd[v]+e[v][i])                    {                        //pathcount[i]=pathcount[v];                        pathd[i]=pathd[v]+e[v][i];    //取路径长度小的                        path[i]=v;                    }                }            }        }    }}int main(){    while(scanf("%d%d",&n,&m)==2)    {        memset(e,inf,sizeof(e));        memset(e2,inf,sizeof(e2));        //memset(vis,0,sizeof(vis));        //memset(d,inf,sizeof(d));        memset(v,0,sizeof(v));        memset(v2,0,sizeof(v2));        for(int i=0; i<n; i++)        {            e[i][i]=0;            e2[i][i]=0;        }        for(int i=1; i<=m; i++)        {            int u,v,p,cost,time;            scanf("%d%d%d%d%d",&u,&v,&p,&cost,&time);            if(e[u][v]>cost)            {                if(p==0)                    e[u][v]=e[v][u]=cost;                else                    e[u][v]=cost;            }            if(e2[u][v]>time)            {                if(p==0)                    e2[u][v]=e2[v][u]=time;                else                    e2[u][v]=time;            }        }        scanf("%d%d",&S,&D);        dijiesi2(S,D);        //printf("Time = %d: ",d[D]);        int tt=d[D];        int sum=0,sum2=0;        int ans=D,ans2=D,DD=D;        while(path[D]!=-1)        {            //cout<<path[D]<<endl;            v[sum++]=path[D];            D=path[D];        }        //for(int i=sum-1;i>=0;i--)        //printf("%d => ",v[i]);        dijiesi1(S,DD);        int dd=d[DD];        while(path[DD]!=-1)        {            //cout<<path[D]<<endl;            v2[sum2++]=path[DD];            DD=path[DD];        }        //printf("%d\n",ans);//        for(int i=sum-1;i>=0;i--)//            cout<<v[i]<<" ";//        cout<<endl;//        for(int i=sum2-1;i>=0;i--)//            cout<<v2[i]<<" ";//        cout<<endl;        int flag=1;//        cout<<sum<<" "<<sum2<<endl;        if(sum2==sum)        {            for(int i=sum-1; i>=0; i--)                if(v[i]!=v2[i])                {                    flag=0;                    break;                }        }        else            flag=0;        if(flag)        {            printf("Time = %d; Distance = %d: ",tt,dd);            for(int i=sum-1; i>=0; i--)                printf("%d => ",v[i]);            printf("%d\n",ans);        }        else        {            printf("Time = %d: ",tt);            for(int i=sum-1; i>=0; i--)                printf("%d => ",v[i]);            printf("%d\n",ans);            printf("Distance = %d: ",dd);            for(int i=sum2-1; i>=0; i--)                printf("%d => ",v2[i]);            printf("%d\n",ans);        }    }    return 0;}