dijkstra应用(PAT甲级中等题)

acwing:1601. 在线地图

输入我们的当前位置和目的地,在线地图就可以推荐一些行进路线。

现在你的工作是向用户推荐两条路线:一条是最短路线,另一条是最快路线。

保证任何询问的两地之间都存在至少一条路线。

输入格式

第一行包含两个整数 N 和 M,表示地图中共有 N个路口(编号 0∼N−1)和 M 个街道。

接下来 M 行,每行描述一条街道,格式如下:

V1 V2 one-way length time

V1 和 V2 是两个路口的编号,表示这两个路口之间存在一条街道,one-way 如果为 1 则表示这条街道是单行道,只能从 V1 前往 V2。如果为 0 表示是双行道,可随意通行。 length 是街道的长度,time 是通过这条街道花费的时间。

最后一行,将给出起点和终点路口的编号。

输出格式

第一行输出路程最短的路线,并输出最短路程 D,格式如下:

Distance = D: source -> v1 -> ... -> destination

第二行输出用时最快的路线,并输出最短用时 T,格式如下:

Time = T: source -> w1 -> ... -> destination

如果最短路线不唯一,则输出用时最短的那条路线(保证唯一)。

如果最快路线不唯一,则输出经过路口最少的那条路线(保证唯一)。

如果最短路线和最快路线经过的路口序列完全相同,则以如下格式将两个信息输出在一行:

Distance = D; Time = T: source -> u1 -> ... -> destination

 思路:

两次dijkstra,分别对距离,时间用dijkstra,注意第二次是时间和节点数(我下意识以为是时间和距离直接waring了)。

#include<bits/stdc++.h>
using namespace std;
const int N=510;
int d[N][N],f[N][N];
int dis[N],fee[N],Cnt[N];
int path1[N],path2[N];
bool st[N];
int n,m,sa,en;
void dijk1()
{
    memset(dis,0x3f,sizeof(dis));
    memset(fee,0x3f,sizeof(fee));
    dis[sa]=0,fee[sa]=0;
    for(int i=0;i<n;i++){
        int t=-1;
        for(int j=0;j<n;j++){
            
            if(!st[j]&&(t==-1||dis[t]>dis[j])){
                t=j;
            }
        }
        st[t]=true;
        for(int j=0;j<n;j++){
            if(dis[j]>dis[t]+d[t][j]){
                dis[j]=d[t][j]+dis[t];
                fee[j]=fee[t]+f[t][j];
                path1[j]=t;
            }else if(dis[j]==dis[t]+d[t][j]){
                if(fee[j]>fee[t]+f[t][j]){
                    fee[j]=fee[t]+f[t][j];
                    path1[j]=t;
                }
            }
        }
    }
}
void dijk2(){
    memset(st,false,sizeof(st));
    memset(dis,0x3f,sizeof(dis));
    memset(fee,0x3f,sizeof(fee));
    dis[sa]=0,fee[sa]=0,Cnt[sa]=1;
    for(int i=0;i<n;i++){
        int t=-1;
        for(int j=0;j<n;j++){
            
            if(!st[j]&&(t==-1||fee[t]>fee[j])){
                t=j;
            }
        }
        st[t]=true;
        for(int j=0;j<n;j++){
            if(fee[j]>fee[t]+f[t][j]){
                Cnt[j]=Cnt[t]+1;
                fee[j]=f[t][j]+fee[t];
                dis[j]=dis[t]+d[t][j];
                path2[j]=t;
            }else if(fee[j]==fee[t]+f[t][j]){
                if(Cnt[j]>Cnt[t]+1){
                    dis[j]=dis[t]+d[t][j];
                    Cnt[j]=Cnt[t]+1;
                    path2[j]=t;
                }
            }
        }
    }
    
}
void solve()
{
    memset(d,0x3f,sizeof(d));
    memset(f,0x3f,sizeof(f));
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int a,b,c,e,g;
        cin>>a>>b>>c>>e>>g;
        if(c==0){
            d[a][b]=min(d[a][b],e),f[a][b]=min(f[a][b],g);
            d[b][a]=min(d[b][a],e),f[b][a]=min(f[b][a],g);
        }else{
            d[a][b]=min(d[a][b],e);
            f[a][b]=min(f[a][b],g);
        }
    }
    cin>>sa>>en;
    int ans1,ans2,ans3,ans4;
    dijk1();
    ans1=dis[en],ans2=fee[en];
    dijk2();
    ans3=dis[en],ans4=fee[en];
    bool flag=0;
    for(int i=en;i!=sa;i=path1[i]){
        int o=path2[i];
        if(path1[i]!=o){
            flag=1;
            break;
        }
    }
    if(flag){
        cout<<"Distance = "<<ans1<<": ";
        int Path1[N],cnt1,Path2[N],cnt2;
        for(int i=en;i!=sa;i=path1[i]){
            Path1[cnt1++]=path1[i];
        }
        for(int i=en;i!=sa;i=path2[i]){
            Path2[cnt2++]=path2[i];
        }
        for(int i=cnt1-1;i>=0;i--){
            cout<<Path1[i]<<" -> ";
        }
        cout<<en<<endl;
        cout<<"Time = "<<ans4<<": ";
        for(int i=cnt2-1;i>=0;i--){
            cout<<Path2[i]<<" -> ";
        }
        cout<<en<<endl;
    }else{
        int Path1[N],cnt1;
        for(int i=en;i!=sa;i=path1[i]){
            Path1[cnt1++]=path1[i];
        }
         cout<<"Distance = "<<ans1<<"; ";
         cout<<"Time = "<<ans4<<": ";
          for(int i=cnt1-1;i>=0;i--){
            cout<<Path1[i]<<" -> ";
        }
        cout<<en<<endl;
         
    }
    
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    int t=1;
    while(t--){
        solve();
    }
    return 0;
}

最后与你共勉,望进步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值