洛谷 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;
}
原文地址:https://www.cnblogs.com/Mercury04/p/9804058.html