高速乘车

本文介绍了一种寻找D星城市间最舒适行车路线的算法。该算法通过二分查找最小速度差,并使用SPFA算法来判断是否能到达终点。适用于对时间要求不高但追求最小速度差的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述
D 星有许多城市, 城市之间通过一种奇怪的高速公路连接, 每条高速公路 都对行驶在上面的汽车限制了固定的速度( 必须以这个速度行驶, 且汽车的提 速和减速是瞬间完成的) , 同时 D 星人对汽车的“舒适度” 有特殊要求, 即乘 车过程中最高速度与最低速度的差越小越舒服 , 但 D 星人对时间却没有很高的 要求。 请编程找出最舒适的行车路线。 (高速公路是双向的) 。

输入
第一行有 2 个正整数 n(2<=n<=200)m(1<=m<=1000),表示有 n 个城市和 m 条高速公路, 城市从 1 到 n 编号。 接 下 来 的 m 行 , 每 行 三 个 正 整 数 S,E,K1<=S,E<=n,SE,1<=K<=1000000 ,表示从 S 到 E 有一条限速为 K 的高速公路。
接下来一行是一个正整数 Q( 1<=Q<=10),表示需要寻找的行车线路条数。
接下来 Q 行每行有 2 个正整数 A,B(1<=A,B<=n,A≠B), 分别表示寻路的起点和终点。

输出
输出 Q 行,每行一个整数, 表示相应舒适度最好的线路的最高速与最低速之差。如果从起点不能到达终点,那么输出“ -1” ( 不包括双引号)。

样例输入
4 4
1 2 2
2 3 4
1 4 1
3 4 2
2
1 3
1 2
样例输出
1
0
提示
【数据范围】
30%的数据保证 2<=n<=50,1<=m<=100,1<=K<=100
50%的数据保证 2<=n<=100,1<=m<=500,1<=K<=100000
100%的数据保证 2<=n<=200,1<=m<=1000,1<=K<=1000000

Solution

初中题感觉没什么好方法阿。。。直接二分最小差,再枚举最小边,然后spfa判断能否到达终点。
复杂度最坏有nmm20,40亿。。。但考虑实际情况,实际上还是很快的。
怎么说呢,还是道水题吧

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define ll unsigned long long
using namespace std;
int n,m,tot,x,y,z,u,v,q,st,ed;
int head[205],Next[2005],to[2005],len[2005];
int f[205],vis[205],g[200005]; 
struct ty
{
    int x,y,z;
}p[1005]; 
int get(int x)
{
    if(f[x]==x) return f[x]; else return f[x]=get(f[x]);
}
void add(int x,int y,int z)
{
    tot++;
    Next[tot]=head[x];
    to[tot]=y;
    len[tot]=z;
    head[x]=tot;
}
int check(int delta)
{
    for(int i=1;i<=m;i++) 
    {
        int limit=p[i].z;
        int t=0,w=1;
        for(int j=1;j<=n;j++) vis[j]=0; 
        g[1]=st,vis[st]=1;
        while(t<w) 
        {
            t++;
            x=g[t];
            if(x==ed) return 1;
            for(int j=head[x];j!=-1;j=Next[j]) 
            {
                y=to[j],z=len[j];
                if(z>=limit&&z<=limit+delta) 
                {
                    if(vis[y]==0) 
                    {
                        w++;
                        g[w]=y;
                        vis[y]=1; 
                    }
                }
            }
        }
    }
    return 0; 
}
int erfen(int l,int r)
{ 
    if(l>r) return l;
    int mid=(l+r)/2;
    if(check(mid)) return erfen(l,mid-1); else return erfen(mid+1,r); 
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++) head[i]=-1,f[i]=i;
    for(int i=1;i<=m;i++) 
    {
        scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z); 
        add(p[i].x,p[i].y,p[i].z); 
        add(p[i].y,p[i].x,p[i].z); 
        u=get(p[i].x); 
        v=get(p[i].y); 
        f[v]=u;
    }
    cin>>q;
    for(int i=1;i<=q;i++) 
    {
        cin>>st>>ed;
        if(get(st)!=get(ed)) cout<<"-1"<<endl; else cout<<erfen(0,1e6)<<endl; 
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值