JZOJ5650. 【NOI2018模拟4.13】公交旅行

题目

这里写图片描述
这里写图片描述

题目大意

就是给出一个n个点的有向图,
每条边的边权是随时间的变化而变化。
求从1出发的,到所有点的最短路。

题解

对于每一条边,
通过它到达下一个点的时间就是要加上它等车的时间。
就是在spfa上面的边权位置稍微修改一下就可以了。

code

#include <queue>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#include <time.h>
#define ll long long
#define N 200003
#define M 103
#define db double
#define P putchar
#define G getchar
#define inf 998244353
#define pi 3.1415926535897932384626433832795
using namespace std;
char ch;
void read(int &n)
{
    n=0;
    ch=G();
    while((ch<'0' || ch>'9') && ch!='-')ch=G();
    ll w=1;
    if(ch=='-')w=-1,ch=G();
    while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
    n*=w;
}

int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
ll abs(ll x){return x<0?-x:x;}
ll sqr(ll x){return x*x;}
void write(ll x){if(x>9) write(x/10);P(x%10+'0');}

int nxt[N*2],to[N*2],k[N*2],b[N*2],lst[N],tot;
int n,m,s,t[N];
int q[N*10],f[N],l,r,x,y,st,v,w;
bool bz[N];

void ins(int x,int y,int t1,int t2)
{
    nxt[++tot]=lst[x];
    to[tot]=y;
    lst[x]=tot;
    k[tot]=t1;
    b[tot]=t2;
}

int main()
{
    freopen("bus.in","r",stdin);
    freopen("bus.out","w",stdout);

    read(n);read(m);
    for(int i=1;i<=m;i++)
    {
        read(s);read(t[1]);
        for(int j=2;j<=s;j++)read(t[j]),ins(t[j-1],t[j],s,j-2);
        ins(t[s],t[1],s,s-1);
    }

    memset(f,127,sizeof(f));
    memset(bz,1,sizeof(bz));

    for(f[q[r=1]=1]=l=bz[1]=0;l<r;)
    {
        st=f[x=q[++l]];
        for(int i=lst[x];i;i=nxt[i])
        {
            y=to[i];w=st/k[i];
            if(st%k[i]>b[i])w++;
            v=w*k[i]+b[i]+1;
            if(f[y]>v)
            {
                f[y]=v;
                if(bz[y])bz[q[++r]=y]=0;
            }
        }
        bz[x]=1;
    }

    for(int i=2;i<=n;i++)
        if(f[i]<f[0])write(f[i]),P(' ');
            else P('-'),P('1'),P(' ');

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值