PAT(甲级)1111 Online Map(最短路)

Description

题目大意:给定一个图,要求你找到最短路和最快的路

Input

n代表n个点,m代表m条边
接下来m行,每行分别输入V1,V2,oneway,length,time
如果oneway=1代表V1,V2是单向的,否则则是双向的,length代表V1到V2的长度,time代表V1到V2的时间
最后一行 source和destination代表起点和终点

Output

如果最短路有多条,求其中最快的;如果最快路有多条,求经过节点最少的;如果最快路和最短路相同,则一起输出,反之则分别输出出来

解题思路

算法标签:最短路Dijstra
1.对路程求最短路,如果最短路相同,则比较时间
2.对时间求最短路,如果最快时间相同,则比较节点数
其实这题就是麻烦,就是求最短路,附加一些条件而已(蒟蒻)

代码

//TSWorld
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
const int N = 505;
const int MAXX = 0x3f3f3f3f;

// 记录距离和时间
int Map[N][N];
int Times[N][N];

// 邻接表
vector<int>edge[N];

// 记录src到每个点的距离和时间,以及点的个数
int dis[N];
int tim[N];
int node[N];
// 记录前驱
int dispre[N];
int timpre[N];
// 记录路径
vector<int>dispath;
vector<int>timpath;
void Dijstra_path(int src,int n)
{
    // 寻找最小边及下标
    int minn = 0,p = 0;

    // 记录该点是否被访问
    bool vis[n+5];
    memset(vis,false,sizeof(vis));

    // dis[i] i到src的距离
    // tim[i] i到src的时间
    for(int i = 0;i < n+3;i++)
        dis[i] = MAXX;
    for(int i = 0;i < n+3;i++)
        tim[i] = MAXX;

    for(int i = 0;i < n;i++)
    {
        dis[i] = Map[src][i];
        tim[i] = Times[src][i];
    }

    for(int i = 0;i < n;i++)
        dispre[i] = i;

    // 初始化src到src距离为0,时间为0
    dis[src] = 0;
    vis[src] = true;
    tim[src] = 0;

    // Dijstra求最短路
    for(int i = 0;i < n;i++)
    {
        minn = MAXX;
        p = -1;
        for(int j = 0;j < n;j++)
        {
            if((!vis[j])&&(minn > dis[j])){
                minn = dis[j];
                p = j;
            }
        }

        if(p == -1)
            break;

        vis[p] = true;

        for(int j = 0;j < edge[p].size();j++)
        {
            if(!vis[edge[p][j]])
            {
                if(dis[edge[p][j]] > dis[p] + Map[p][edge[p][j]])
                {
                    dis[edge[p][j]] = dis[p] + Map[p][edge[p][j]];
                    tim[edge[p][j]] = tim[p] + Times[p][edge[p][j]];
                    dispre[edge[p][j]] = p;
                }
                else if(dis[edge[p][j]] == dis[p] + Map[p][edge[p][j]])
                {
                    if(tim[edge[p][j]] > tim[p] + Times[p][edge[p][j]]){
                        tim[edge[p][j]] = tim[p] + Times[p][edge[p][j]];
                        dispre[edge[p][j]] = p;
                    }
                }
            }
        }
    }

}

void Dijstra_time(int src,int n)
{
    // 寻找最小边及下标
    int minn = 0,p = 0;

    // 记录该点是否被访问
    bool vis[n+5];
    memset(vis,false,sizeof(vis));

    // 初始化Tim
    for(int i = 0;i < n+3;i++)
        tim[i] = MAXX;
    for(int i = 0;i < n;i++){
        tim[i] = Times[src][i];
        timpre[i] = i;
    }

    tim[src] = 0;
    vis[src] = true;

    // Dijstra
    for(int i = 0;i < n;i++)
    {
        minn = MAXX,p = -1;
        for(int j = 0;j < n;j++)
        {
            if((!vis[j])&&(minn > tim[j])){
                minn = tim[j];
                p  = j;
            }
        }

        if(p == -1)
            break;
        vis[p] = true;

        for(int j = 0;j < edge[p].size();j++)
        {
            if(!vis[edge[p][j]])
            {
                if(tim[edge[p][j]] > tim[p] + Times[p][edge[p][j]])
                {
                    tim[edge[p][j]] = tim[p] + Times[p][edge[p][j]];
                    node[edge[p][j]] = node[p] + 1;
                    timpre[edge[p][j]] = p;
                }
                else if((tim[edge[p][j]] == tim[p] + Times[p][edge[p][j]])&&(node[p]+1 < node[edge[p][j]]))
                {
                    node[edge[p][j]] = node[p] +1;
                    timpre[edge[p][j]] = p;
                }
            }
        }
    }
}   

void Print_path(int dest)
{
    if(dispre[dest] == dest){
        dispath.push_back(dest);
        return;
    }
    Print_path(dispre[dest]);
    dispath.push_back(dest);
}

void Print_tim(int dest)
{
    if(timpre[dest] == dest){
        timpath.push_back(dest);
        return;
    }
    Print_tim(timpre[dest]);
    timpath.push_back(dest);
}
int main()
{
    int n = 0,m = 0;
    int one_way = 0,length = 0,time = 0;
    int source = 0,destination = 0;
    int V1 = 0,V2 = 0;

    cin>>n>>m;

    for(int i = 0;i < n+1;i++)
        for(int j = 0;j < n+1;j++){
            Map[i][j] = MAXX;
            Times[i][j] = MAXX;
        }
    for(int i = 1;i <= m;i++)
    {
        cin>>V1>>V2>>one_way>>length>>time;
        if(one_way == 1){
            Map[V1][V2] = length;
            Times[V1][V2] = time;
            edge[V1].push_back(V2);
        }
        else
        {
            Map[V1][V2] = length;
            Times[V1][V2] = time;
            edge[V1].push_back(V2);
            
            Map[V2][V1] = Map[V1][V2];
            Times[V2][V1] = Times[V1][V2];
            edge[V2].push_back(V1); 
        }
    }

    cin>>source>>destination;

    Dijstra_path(source,n);

    cout<<"Distance = "<<dis[destination];

    dispath.push_back(source);
    Print_path(destination);

    Dijstra_time(source,n);
    timpath.push_back(source);
    Print_tim(destination);

    if(timpath == dispath)
    {
        cout<<"; Time = "<<tim[destination]<<": ";
        for(int i = 0;i < dispath.size();i++)
            if(i == 0)
                cout<<dispath[i];
            else
                cout<<" -> "<<dispath[i];
    }
    else
    {
        cout<<": ";
        for(int i = 0;i < dispath.size();i++)
            if(i==0)
                cout<<dispath[i];
            else
                cout<<" -> "<<dispath[i];
        cout<<endl;
        cout<<"Time = "<<tim[destination]<<": ";
        for(int i = 0;i < timpath.size();i++)
            if(i==0)
                cout<<timpath[i];
            else
                cout<<" -> "<<timpath[i];
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值