zoukankan      html  css  js  c++  java
  • 洛谷 P1266 速度限制 最短路+SPFA算法

    题面

    题目链接

    P1266 速度限制

    题目描述

    在这个繁忙的社会中,我们往往不再去选择最短的道路,而是选择最快的路线。开车时每条道路的限速成为最关键的问题。不幸的是,有一些限速的标志丢失了,因此你无法得知应该开多快。一种可以辩解的解决方案是,按照原来的速度行驶。你的任务是计算两地间的最快路线。

    你将获得一份现代化城市的道路交通信息。为了使问题简化,地图只包括路口和道路。每条道路是有向的,只连接了两条道路,并且最多只有一块限速标志,位于路的起点。两地A和B,最多只有一条道路从A连接到B。你可以假设加速能够在瞬间完成并且不会有交通堵塞等情况影响你。当然,你的车速不能超过当前的速度限制

    输入输出格式

    输入格式

    第一行是3个整数 $ N $ , $ M $ 和 $ D (2 leq N leq 150) $ ,表示道路的数目,用 $ 0..N-1 $ 标记。 $ M $ 是道路的总数, $ D $ 表示你的目的地。

    接下来的 $ M $ 行,每行描述一条道路,每行有4个整数 $ A(0 leq A<N) $ , $ B(0 leq B<N) $ , $ V(0 leq V leq 500) $ and $ L(1 leq L≤500) $ ,这条路是从A到B的,速度限制是 $ V $ ,长度为 $ L $ 。如果 $ V $ 是0,表示这条路的限速未知。

    如果 $ V $ 不为0,则经过该路的时间 $ T=L/V $ 。否则 $ T=L/Vold $ , $ Vold $ 是你到达该路口前的速度。开始时你位于0点,并且速度为70。

    输出格式

    输出文件仅一行整数,表示从 $ 0 $ 到 $ D $ 经过的城市。

    输出的顺序必须按照你经过这些城市的顺序,以 $ 0 $ 开始,以 $ D $ 结束。仅有一条最快路线。

    输入输出样例

    输入样例

    6 15 1
    0 1 25 68
    0 2 30 50
    0 5 0 101
    1 2 70 77
    1 3 35 42
    2 0 0 22
    2 1 40 86
    2 3 0 23
    2 4 45 40
    3 1 64 14
    3 5 0 23
    4 1 95 8
    5 1 0 84
    5 2 90 64
    5 3 36 40
    

    输出样例

    0 5 2 3 1
    

    说明

    【时空限制】

    1000ms,128MB

    思路

    每一次转移时,还需要考虑速度,所以可以考虑开两维数组。

    AC代码

    #include<bits/stdc++.h>
    const int maxn=160;
    const int maxm=maxn*maxn;
    const int maxv=510;
    using namespace std;
    
    int n,m,ed;
    int tot,to[maxm],nxt[maxm],l[maxm],V[maxm],head[maxn];
    double dis[maxn][maxv];
    bool vis[maxn][maxv];
    int ansv,Out[maxn],cnt;
    struct Pre
    {
        int x,v;
    }pre[maxn][maxv];
    
    void Add(int u,int v,int mv,int len)
    {
        to[++tot]=v,nxt[tot]=head[u],l[tot]=len,V[tot]=mv,head[u]=tot;
    }
    
    void spfa()
    {
        memset(dis,66,sizeof(dis));
        queue< pair<int,int> > q;
        q.push(make_pair(1,70));vis[1][70]=true;dis[1][70]=0;
        while(!q.empty())
        {
            int ux=q.front().first;
            int uv=q.front().second;
            q.pop();vis[ux][uv]=false;
            for(int i=head[ux];i;i=nxt[i])
            {
                int vx=to[i];
                int vv=(V[i]? V[i]:uv);
                if(dis[vx][vv]>dis[ux][uv]+l[i]*1.0/vv)
                {
                    pre[vx][vv]=(Pre){ux,uv};
                    dis[vx][vv]=dis[ux][uv]+l[i]*1.0/vv;
                    if(!vis[vx][vv])
                    {
                        q.push(make_pair(vx,vv));
                        vis[vx][vv]=true;
                    }
                }
            }
        }
    }
    
    int main()
    {
        scanf("%d%d%d",&n,&m,&ed);ed++;
        for(int i=1,u,v,mv,len;i<=m;i++)
            scanf("%d%d%d%d",&u,&v,&mv,&len),u++,v++,Add(u,v,mv,len);
        spfa();
        for(int i=1;i<=maxv-5;i++) if(dis[ed][ansv]>dis[ed][i]) ansv=i;
        int nx=ed,nv=ansv;
        while(nx)
        {
            Out[++cnt]=nx;
            int tmp1=pre[nx][nv].x;
            int tmp2=pre[nx][nv].v;
            nx=tmp1,nv=tmp2;
        }
        for(int i=cnt;i>=1;i--) printf("%d ",Out[i]-1);
        return 0;
    }
    
  • 相关阅读:
    《激荡三十年》七、国企难破局—“裁缝神话”步鑫生
    《激荡三十年》六、个体户——“傻子”年广久
    《激荡三十年》五、乡镇企业的异军突起——鲁冠球
    《激荡三十年》四、改革第一将—“老板”袁庚
    《激荡三十年》三、改革开放伊始、邓公开国门
    《激荡三十年》二、改革开放前的中国(下)
    《激荡三十年》一、改革开放前的中国(上)
    shell编程之sleep的运用
    shell编程之数组和关联数组
    shell编程之重定向
  • 原文地址:https://www.cnblogs.com/Mercury04/p/9804058.html
Copyright © 2011-2022 走看看