PAT 1111 Online Map

这一题意根据点之间的距离和时间,求某两点之间的距离最短路径和时间最短路径。
距离最短路径有相同,输出时间最短的。时间最短路径有相同,输出经过的节点最少的。
按指定的格式输出。
这一题用djs最短路径,一开始使用了dfs递归写法,但是由于函数递归的效率低下,导致最后一点超时。然后想改成循环的写法,看了一下自己以前关于最短路径的循环的代码,改了半天,发现没有通过,才发现自己用错了,用成了队列。dfs应该使用栈, 改完后,只有最后两个通过。后来在修改成别人的代码过程中,发现自己犯了一个低级错误,赋值赋错了,又回到自己的代码修改,在此过程中从别人那得到的理解对自己的代码进行优化,终于改出来。
根据每个点和相连接的点的距离,用数组把每个点的dist更新到最短的dist,然后将这个点标记为访问过。路径的保存是反向保存,后一节点指向前一个节点,这样可以保证更新了以后,后一个节点指向的前一个节点,一定是其最短距离相连的点。
(用时:7:51:03.51)

#include <bits/stdc++.h>
using namespace std;
#define INF 1000000
struct OnlineMap {
    int vEnd;
    int length;
    int time;
};

void ShortestPath(int source,int destination,vector<OnlineMap> omp[],int n)
{

    int vis[n]= {0};
    stack<int> sta;
    int dist[n];
    int time[n];
    int sPath[n];
    int tPath[n];
    for(int i=0; i<n; i++) {
        dist[i] = INF;
        time[i] = INF;
        sPath[i] =INF;
        tPath[i] =INF;
    }

    for(int i=0; i<omp[source].size(); i++) {
        //到这一点的最短距离
        dist[omp[source][i].vEnd] = omp[source][i].length;
        //到这一点的时间
        time[omp[source][i].vEnd] = omp[source][i].time;
        sPath[omp[source][i].vEnd] =source;
        tPath[omp[source][i].vEnd] =source;
    }

    dist[source] = 0;
    time[source] = 0;
    sta.push(source);

    while(!sta.empty()) {
        int index = sta.top();
        sta.pop();
        if(index!=destination) {
            vis[index] = 1;
            for(int i=0; i<omp[index].size(); i++) {
               //无论有没有访问过,都要检测其dist
                if(dist[index] + omp[index][i].length< dist[ omp[index][i].vEnd]) {
                    dist[omp[index][i].vEnd] = dist[index] + omp[index][i].length;
                    time[omp[index][i].vEnd] = time[index] + omp[index][i].time;
                    sPath[omp[index][i].vEnd] =  index;
                } else if(dist[index] + omp[index][i].length == dist[ omp[index][i].vEnd]) {
                    if( time[index] + omp[index][i].time < time[omp[index][i].vEnd]) {
                        time[omp[index][i].vEnd] = time[index] + omp[index][i].time;
                        sPath[omp[index][i].vEnd] =  index;
                    }
                }
                if(!vis[omp[index][i].vEnd]) {
                    sta.push(omp[index][i].vEnd);
                }
            }
        }
    }

    vector<int> sP;
    int t = destination;
    while(t!=source) {
        sP.push_back(t);
        t=sPath[t];
    }
    sP.push_back(source);

    int distNum[n]= {0};
    for(int i=0; i<n; i++) {
        distNum[i] = INF;
        vis[i] = 0;
    }
    time[source] = 0;
    distNum[source] = 0;
    sta.push(source);
    while(!sta.empty()) {
        int index = sta.top();
        sta.pop();

        if(index!=destination) {
            vis[index] = 1;
            for(int i=0; i<omp[index].size(); i++) {
 
                if(time[index] + omp[index][i].time< time[omp[index][i].vEnd]) {

                    distNum[omp[index][i].vEnd] =   distNum[index] + 1;
                    time[omp[index][i].vEnd] = time[index] + omp[index][i].time;
                    tPath[omp[index][i].vEnd] = index;

                } else if(time[index] + omp[index][i].time==time[omp[index][i].vEnd]) {
                    if(distNum[index] + 1<  distNum[omp[index][i].vEnd] ) {
                        distNum[omp[index][i].vEnd] = distNum[index] + 1;
                        tPath[omp[index][i].vEnd] = index;
                    }
                }
                if(! vis[omp[index][i].vEnd]) {
                    sta.push(omp[index][i].vEnd);
                }
            }
        }
    }

    vector<int> timeP;
    t = destination;
    while(t!=source) {
        timeP.push_back(t);
        t=tPath[t];
    }
    timeP.push_back(source);

    printf("Distance = %d",dist[destination]);
    if(timeP==sP) {
        printf("; Time = %d:",time[destination]);
        for(int i=sP.size()-1; i>=0; i--) {
            if(i==sP.size()-1) {
                printf(" %d",sP[i]);
            } else {
                printf(" -> %d",sP[i]);
            }

        }
        printf("\n");
    } else {
        printf(":");
        for(int i=sP.size()-1; i>=0; i--) {
            if(i==sP.size()-1) {

                printf(" %d",sP[i]);
            } else {
                printf(" -> %d",sP[i]);
            }

        }
        printf("\nTime = %d:",time[destination]);
        for(int i=timeP.size()-1; i>=0; i--) {
            if(i==timeP.size()-1) {
                printf(" %d",timeP[i]);
            } else {
                printf(" -> %d",timeP[i]);
            }

        }
        printf("\n");
    }
}

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);

    int oneway,time,length,v1,v2;
    vector<OnlineMap> vec[n];
    for(int i=0; i<m; i++) {

        scanf("%d%d%d%d%d",&v1,&v2,&oneway,&length,&time);
        OnlineMap onlineA;
        onlineA.vEnd = v2;
        onlineA.time = time;
        onlineA.length = length;
        vec[v1].push_back(onlineA);
        if(!oneway) {
            OnlineMap  onlineB;
            onlineB.vEnd = v1;
            onlineB.time = time;
            onlineB.length = length;
            vec[v2].push_back(onlineB);
        }
    }

    scanf("%d%d",&v1,&v2);
    ShortestPath(v1,v2, vec, n);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值