链接:https://ac.nowcoder.com/acm/contest/7412/H
来源:牛客网
题目描述
牛牛早上起床一看,自己睡过了,赶紧起床准备去学校,他去学校只有两种方式,坐公交车和步行,牛牛去学校是一条直线,这条直线上总共有n个车站,车站之间的距离都是相等的,每个车站只有一种公交车
a
i
a_i
ai,每个公交车只在对应的公交站停车,每个公交车的速度也不一样,第i种公交车过一站的时间需要
t
i
t_i
ti,并且公交车是单向行驶,只能从左到到右,走路可以任意走,然而牛牛自己步行走一站需要的时间为T,恰好牛牛家和学校都在某一个站点,分别为s和t,问最少需要多少时间牛牛才能到学校?
输入描述:
第一行为正整数 n,m,s,t,T 分别表示直线上的车站个数,公交车种数,牛牛家的位置,学校的位置和牛牛自己步行走一站需要的时间
(
n
,
m
≤
1
×
1
0
5
,
1
≤
s
,
t
≤
n
,
1
≤
T
≤
1
×
1
0
4
)
(n,m\leq 1×10^5,1\leq s,t\leq n,1\leq T\leq 1×10^4)
(n,m≤1×105,1≤s,t≤n,1≤T≤1×104)
第二行有 m 个正整数表示每种公交车过一站需要的时间为
t
i
(
1
≤
t
i
≤
1
×
1
0
4
)
t_i(1\leq t_i \leq 1×10^4)
ti(1≤ti≤1×104)
第三行有 nn 个正整数表示每个车站可停的公交车为
a
i
(
1
≤
a
i
≤
m
)
a_i (1\leq a_i\leq m)
ai(1≤ai≤m)
输出描述:
输出牛牛从家到学校的最少时间
思路:公交车单向行驶,牛牛可以任意走,所以每一步要么牛牛步行前进或后退一站,要么坐公交车到相应公交车的下一站。根据响应速度建边然后跑一个最短路就好了。
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<set>
#include<string>
#include<queue>
using namespace std;
#define LL long long
#define uLL unsigned long long
#define PII pair<int,int>
#define mid ((l + r)>>1)
#define chl (root<<1)
#define chr (root<<1|1)
const int manx = 1e5 + 10;
const int INF = 0x3fffffff;
const int mod = 1e4+7;
int n,m,s,t,T,x;
int head[manx],cou=0,cost[manx],p[manx],dis[manx],vs[manx];
struct node{
int e,len,bf;
}edge[manx<<2];
struct poi{
int pos,len;
friend bool operator<(poi a,poi b){
return a.len>b.len;
}
};
void add(int s,int e,int len)
{
edge[cou]=node{e,len,head[s]};
head[s]=cou++;
}
void init()
{
memset(head,-1,sizeof head);
for(int i=1;i<=n;i++){
dis[i]=2e9;
vs[i]=0;
}
}
void dij(int s,int e)
{
priority_queue<poi>qu;
dis[s]=0;
poi now;
now.len=0,now.pos=s;
qu.push(now);
while(!qu.empty()&&vs[e]==0)
{
now=qu.top();
qu.pop();
if(vs[now.pos])continue;
vs[now.pos]=1;
for(int i=head[now.pos];~i;i=edge[i].bf){
int pos=edge[i].e;
if(vs[pos])continue;
if(dis[pos]>now.len+edge[i].len){
dis[pos]=now.len+edge[i].len;
qu.push(poi{pos,dis[pos]});
}
}
}
}
int main()
{
scanf("%d%d%d%d%d",&n,&m,&s,&t,&T);
init();
for(int i=1;i<=m;i++){
scanf("%d",&cost[i]);
}
memset(p,0,sizeof p);
for(int i=1;i<=n;i++){
scanf("%d",&x);
if(p[x])
add(p[x],i,cost[x]);
p[x]=i;
if(i<n){
add(i,i+1,T);
add(i+1,i,T);
}
}
dij(s,t);
printf("%d\n",dis[t]);
return 0;
}