L3-007 天梯地图 (基于优先队列和dijkstra实现)

L3-007 天梯地图 (基于优先队列和dijkstra实现)

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

输入格式:

输入在第一行给出两个正整数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 => ... => 终点

优先队列的使用技巧

priority_queue 默认是大顶堆,采用比较方式是 < 
struct T{
	int data;
    friend bool operator < (const T& a,const T& b){
        //默认是大顶(即返回 a.data < b.data ),取反为小顶
        return a.data>b.data; 
    }
};
priority_queue<T> pq;//p按data小的在前

完整代码

#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=500+1;
int g_len[N][N];
int g_time[N][N];
int graph_size;
int ans_min_tiem,ans_min_len;

void input_graph(){
    int m;
    cin>>graph_size>>m;
    while(m--){
        int v1,v2,one_way,length,time;
        cin>>v1>>v2>>one_way>>length>>time;
        g_len[v1][v2]=length;
        g_time[v1][v2]=time;
        if(one_way!=1){
            g_len[v2][v1]=length;
            g_time[v2][v1]=time;
        }
    }
}

/*如果最快到达路线不唯一,则输出几条最快路线中最短的那条*/
struct q_ele1{
    int node;
    int time;
    int len;
    friend bool operator<(const q_ele1&a,const q_ele1&b){
        if(a.time==b.time){
            return a.len>b.len;
        }
        else return a.time>b.time;
    }
};
/*而如果最短距离的路线不唯一,则输出途径节点数最少的那条*/
struct q_ele2{
    int node;
    int len;
    int cnt;
    friend bool operator<(const q_ele2&a,const q_ele2&b){
        if(a.len==b.len){
            return a.cnt>b.cnt;
        }
        else return a.len>b.len; 
    }
};

vector<int> dijkstra1(int s,int e){
    int t[N],d[N],path[N];
    bool vis[N];
    memset(t,-1,sizeof(t));
    memset(d,-1,sizeof(d));
    memset(vis,0,sizeof(vis));
    priority_queue<q_ele1> p;
    p.push({s,0,0});
    t[s]=0;
    d[s]=0;
    while(!p.empty()){
        auto cur=p.top();
        p.pop();
        if(vis[cur.node]) continue;
        vis[cur.node]=true;
        if(cur.node==e) break;
        for(int i=0;i<graph_size;i++){
            if(!vis[i]&&g_time[cur.node][i]){
                if(t[i]==-1||cur.time+g_time[cur.node][i]<t[i]){
                    path[i]=cur.node;
                    // cout<<path[i];
                    t[i]=cur.time+g_time[cur.node][i];
                    d[i]=cur.len+g_len[cur.node][i];
                    p.push({i,t[i],d[i]});
                }
                else if(cur.time+g_time[cur.node][i]==t[i]&&cur.len+g_len[cur.node][i]<d[i]){
                    path[i]=cur.node;
                    // cout<<path[i];
                    d[i]=cur.len+g_len[cur.node][i];
                    p.push({i,t[i],d[i]});
                }
            }
        }
    }
    ans_min_tiem=t[e];
    vector<int> ans;
    ans.push_back(e);
    for(int i=path[e];i!=s;i=path[i]) ans.push_back(i);
    ans.push_back(s);
    reverse(ans.begin(),ans.end());
    return ans;
}

vector<int> dijkstra2(int s,int e){
    int cnt[N],d[N],path[N];
    bool vis[N];
    memset(d,-1,sizeof(d));
    memset(cnt,-1,sizeof(cnt));
    memset(vis,0,sizeof(vis));
    priority_queue<q_ele2> p;
    p.push({s,0,0});
    d[s]=0;
    cnt[s]=0;
    while(!p.empty()){
        auto cur=p.top();
        p.pop();
        if(vis[cur.node]) continue;
        vis[cur.node]=true;
        if(cur.node==e) break;
        for(int i=0;i<graph_size;i++){
            if(!vis[i]&&g_len[cur.node][i]){
                if(d[i]==-1||cur.len+g_len[cur.node][i]<d[i]){
                    path[i]=cur.node;
                    d[i]=cur.len+g_len[cur.node][i];
                    cnt[i]=cur.cnt+1;
                    p.push({i,d[i],cnt[i]});
                }
                else if(cur.len+g_len[cur.node][i]==d[i]&&cur.cnt+1<cnt[i]){
                    path[i]=cur.node;
                    cnt[i]=cur.cnt+1;
                    p.push({i,d[i],cnt[i]});
                }
            }
        }
    }
    ans_min_len=d[e];
    vector<int> ans;
    ans.push_back(e);
    for(int i=path[e];i!=s;i=path[i]) ans.push_back(i);
    ans.push_back(s);
    reverse(ans.begin(),ans.end());
    return ans;
}

void solve(){
    int s,e;
    cin>>s>>e;
    auto path_1=dijkstra1(s,e);
    auto path_2=dijkstra2(s,e);
    cout<<"Time = "<<ans_min_tiem;
    if(path_1!=path_2){
        cout<<": "<<s;
        for(int i=1;i<path_1.size();i++){
            cout<<" => "<<path_1[i];
        }
        cout<<endl;
    }
    else{
        cout<<"; ";
    }
    cout<<"Distance = "<<ans_min_len;
    cout<<": "<<s;
    for(int i=1;i<path_2.size();i++){
        cout<<" => "<<path_2[i];
    }
}

int main(){
    input_graph();
    solve();
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值