[2018.03.29 T2] 公交旅行

6 篇文章 0 订阅
4 篇文章 0 订阅

暂无连接

公交旅行

【题目描述】

蒜头是一位优秀的旅行家。

人类的发展总离不开一代又一代的探险者先驱。追寻前人的轨迹,今天的蒜头到了一个有趣的城市, 和蒜头居住的城市一样有趣。

在这个城市中有 n 个站台和 m 条公交线路,第 i 条公交线路由 ti 个站台组成,记为 si,1,si,2,…,si,ti 。在 0 时刻,第 i 辆公交车会处在 si,1 站台,之后每个时刻公交都会到达路线中的下一个站台。当公交到达终点站后,它下一个时刻将会回到出发的站台,注意一座站台可能在一条线路中出现多次,但不会相邻。

在 0 时刻,蒜头处在站台 1 。如果在某一时刻蒜头和公交在同一个站台,那么蒜头就可以上这辆公交车,并在任意时刻下车,上下车的过程并不会花费时间。作为一位环保的优秀旅行家,蒜头热爱乘坐公交出行。现在蒜头想要知道,如果他只乘坐公交出行,他分别能最早在何时到达每个站台,或是告诉他这 是不可能的。

注意,蒜头一次只能乘坐一辆车,但在通往某个站台的过程中,蒜头可以乘坐许多辆不同的公交车。

【输入】

输入的第一行是两个整数 n,m,分别表示站台和线路的个数。

接下来的 m 行,每行的第一个数为 ti ,表示线路的长度,随后的 ti 个整数描述一条公交线路。

【输出】

共输出 1 行 n−1 个数,第 i 个数表示到达站台 i+1 的最小时间。如果不能到达,输出 −1。

【输入样例】

8 4
2 5 4
3 6 1 2
4 4 2 1 3
2 7 8

【输出样例】

2 3 4 6 3 -1 -1

【提示】
【数据范围】

对于 100% 的数据,ti≥2。

123429271430n501035×103105m501035×103105ti3002×1041052×105 子 任 务 编 号 子 任 务 分 值 n ≤ m ≤ ∑ t i ≤ 1 29 50 50 300 2 27 10 3 10 3 2 × 10 4 3 14 5 × 10 3 5 × 10 3 10 5 4 30 10 5 10 5 2 × 10 5

第一个子任务测试点:1,2,…7;

第二个子任务测试点:8,9,10;

第三个子任务测试点:11,12,13;

第四个子任务测试点:14,15,…,29。

题解

处理环和等车是非常麻烦的,所以我们不如直接建图跑最短路,在跑最短路的时候直接加上等车的时间就好了。

计算等车时间需要记录当前时间,环的大小和当前车站在环里的位置,具体见代码。

代码
#include<bits/stdc++.h>
using namespace std;
const int M=1e5+5;
struct sd{int to,id,pos;};
int n,m,dis[M],vis[M],len[M];
vector<sd>mmp[M];
void in()
{
    int a,p1,p2,st;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i)
    {
        scanf("%d%d",&a,&st);
        len[i]=a;p1=st;
        for(int j=2;j<=a;++j)
        scanf("%d",&p2),mmp[p1].push_back((sd){p2,i,j-1}),p1=p2;
        mmp[p1].push_back((sd){st,i,0});
    }
}
int get(int d,int p,int l)
{return (p-(d%l)+l)%l+d;}
void SPFA()
{
    memset(dis,127,sizeof(dis));
    queue<int>dui;
    dui.push(1),vis[1]=1,dis[1]=0;
    int f,t,d;
    while(!dui.empty())
    {
        f=dui.front();
        dui.pop(),vis[f]=0;
        for(int i=mmp[f].size()-1;i>=0;--i)
        {
            t=mmp[f][i].to;d=get(dis[f]+1,mmp[f][i].pos,len[mmp[f][i].id]);
            if(dis[t]>d)
            {
                dis[t]=d;
                if(vis[t])continue;
                dui.push(t),vis[t]=1;
            }
        }
    }
}
void ac()
{
    SPFA();
    for(int i=2;i<=n;++i)
    if(dis[i]>1e9)printf("-1 ");
    else printf("%d ",dis[i]);
}
int main()
{
    in();ac();
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值