天梯地图(Dijkstra变形)

来源:互联网 发布:戏精 知乎 编辑:程序博客网 时间:2024/05/10 11:37
天梯地图  

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

输入格式:

输入在第一行给出两个正整数N(2 \le N \le 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
关键在于如果最快到达路线不唯一,则输出几条最快路线中最短的那条,题目保证这条路线是唯一的。
而如果最短距离的路线不唯一,则输出途径节点数最少的那条,题目保证这条路线是唯一的。
根据这个,在Dijkstra算法中,更新点的d值时候,不仅仅要在d[u]>d[v]+G[v][u]时候更新,在等于的时候也有可能要更新,等于的时候要进行判断,然后看是否更新。
等于更新的条件容易出bug,在这被死循环了好久。
题目地址:https://www.patest.cn/contests/gplt/L3-007
代码:
#include <iostream>#include <cstdio>#include <cmath>#include <queue>#include <stack>#include <map>#include <algorithm>#include <vector>#include <string>#include <cstring>#include <sstream>#define INF 100000000using namespace std;int G[505][505];  //lengthint M[505][505];  //timeint n,m;int s,e;int path[1005];int t[1005];bool used[1005];int dis[505];int has[505];int ppath[505];int jiedian(int u){    int tmp=0;    while(ppath[u]!=s)    {        tmp++;        u=ppath[u];    }    tmp++;    return tmp;}void Dijkstra2(){    fill(has,has+n,false);    fill(dis,dis+n,INF);    memset(ppath,-1,sizeof(ppath));    dis[s]=0;    while(1)    {        int v=-1;        for(int u=0;u<n;u++)        {            if((v==-1 || dis[u]<dis[v]) && !has[u])            {                v=u;            }        }        if(v==-1) return;        has[v]=true;        for(int u=0;u<n;u++)        {            if(dis[u]>dis[v]+G[v][u])            {                dis[u]=dis[v]+G[v][u];                ppath[u]=v;            }            else if((dis[u]==dis[v]+G[v][u]) && dis[v] &&(v!=u))            {                int cntyuan=jiedian(u);                int cntnew=jiedian(v)+1;                if(cntnew<cntyuan)                {                    dis[u]=dis[v]+G[v][u];                    ppath[u]=v;                }            }        }    }}int distance(int u){    int tmp=0;    while(path[u]!=s)    {        tmp+=G[path[u]][u];        u=path[u];    }    tmp+=G[s][u];    return tmp;}void Dijkstra(){    fill(t,t+n,INF);    fill(used,used+n,false);    memset(path,-1,sizeof(path));    t[s]=0;    while(1)    {        int v=-1;        for(int u=0;u<n;u++)        {            if((v==-1 || t[u]<t[v]) &&!used[u])            {                v=u;            }        }        if(v==-1) return;        used[v]=true;        for(int u=0;u<n;u++)        {            if(t[u]>t[v]+M[v][u])            {                t[u]=t[v]+M[v][u];                path[u]=v;            }            else if((t[u]==t[v]+M[v][u]) &&t[v])            {                int oridis=distance(u);                int newdis=distance(v);                newdis=newdis+G[v][u];                if(newdis<oridis)                {                    t[u]=t[v]+M[v][u];                    path[u]=v;                }            }        }    }}int path1[505];int cnt1;int path2[505];int cnt2;void Recover(){    int u=e;    while(u!=s)    {        path1[cnt1++]=u;        u=path[u];    }    path1[cnt1++]=u;    reverse(path1,path1+cnt1);    u=e;    while(u!=s)    {        path2[cnt2++]=u;        u=ppath[u];    }    path2[cnt2++]=u;    reverse(path2,path2+cnt2);}bool judge(){    if(cnt1!=cnt2) return false;    for(int i=0;i<cnt1;i++)    {        if(path1[i]!=path2[i]) return false;    }    return true;}int TIME(){    int tmp=0;    for(int i=0;i<cnt1-1;i++)    {        tmp+=M[path1[i]][path1[i+1]];    }    return tmp;}int DIS(){    int tmp=0;    for(int i=0;i<cnt2-1;i++)    {        tmp+=G[path2[i]][path2[i+1]];    }    return tmp;}int main(){    scanf("%d%d",&n,&m);    for(int i=0;i<n;i++)    {        for(int j=0;j<n;j++)        {            G[i][j]=M[i][j]=INF;        }        G[i][i]=M[i][i]=0;    }    for(int i=0;i<m;i++)    {        int x,y,z,l,t;        scanf("%d%d%d%d%d",&x,&y,&z,&l,&t);        if(z==1)        {            G[x][y]=l;            M[x][y]=t;        }        else        {            G[x][y]=G[y][x]=l;            M[x][y]=M[y][x]=t;        }    }    scanf("%d%d",&s,&e);    Dijkstra();    Dijkstra2();    Recover();    int time=TIME();    int di=DIS();    if(judge())    {        printf("Time = %d; Distance = %d: ",time,di);        for(int i=0;i<cnt1;i++)        {            if(i==0) printf("%d",path1[i]);            else printf(" => %d",path1[i]);        }        printf("\n");    }    else    {        printf("Time = %d: ",time);        for(int i=0;i<cnt1;i++)        {            if(i==0) printf("%d",path1[i]);            else printf(" => %d",path1[i]);        }        printf("\n");        printf("Distance = %d: ",di);        for(int i=0;i<cnt2;i++)        {            if(i==0) printf("%d",path2[i]);            else printf(" => %d",path2[i]);        }    }    return 0;}


0 0