P4678 [BalticOI 2005] Bus Trip 题解

发布时间 2023-10-26 21:05:54作者: lava__44

P4678 [BalticOI 2005] Bus Trip 题解(RE:题解再改造!!)

贴码

#include<bits/stdc++.h>
#define MAXN 500010
using namespace std;
//ifstream is("trip.in",ios::in);
//ofstream os("trip.out",ios::out);
//#define cin is
//#define cout os
int n,m,p,t,tote,dist[MAXN],ans[MAXN];
struct Bus {
int x,t,idx,dist;
}b[MAXN];
void build(int x,int t,int idx,int dist){
b[++tote]={x,t,idx,dist};
}
bool cmp(const Bus &x,const Bus &y){
return x.t==y.t?x.dist>y.dist:x.t<y.t;
}
int main(){
ios::sync_with_stdio(0);
cin>>n>>m>>p>>t;
for(int i=1,s,t,a,b,c,d;i<=m;i++){
cin>>s>>t>>a>>b>>c>>d;
build(s,a,i,0);
build(t,d,i,c-b);
}
build(n+1,t,0,-0x3f3f3f3f);
sort(b+1,b+tote+1,cmp);
memset(dist,250,sizeof(dist));
dist[1]=0;
for(int i=1;i<=tote;i++){
if(b[i].x==n+1) break;
if(!b[i].dist) ans[b[i].idx]=dist[b[i].x];
else dist[b[i].x]=max(dist[b[i].x],ans[b[i].idx]+b[i].dist);
}
(dist[p]<0)?cout<<"-1":cout<<t-dist[p];
return 0;
}

正文

本题关键在于把最坏等待时间转化成中间乘坐公交的最长时间。

即每次乘车都看成a_i上车b_i开车,c_i抵达d_i下车,等待时间拉满。

此时车上时间为c_i-b_i

build建点时存储的几个变量:出发点/到达点,出发/到达最终时间,第idx号公交车,b_i.dist为这班车到达此点的乘车耗时。

把边排序的时候使用的排序规则为:

  • 最终时间相同时,乘车时间越长排越前面

  • 最终时间不同时,最终时间更长排越后面

dist需赋一个负的极小值(赋250或0xcf均可,赋250是因为250的二进制是1111\ 1010使用memset赋值保证最高位是负,赞美兰豆,虽然他是口糊的)

接下来枚举每个点,若为起点则将对应的ans赋为到该点的dist值;

若为终点,则用该点的ans+到该点那班车车上所花的时间值(b.dist)更新该点的dist值。

若到达p点是dist_p值小于零输出-1,若不是则输出t-dist_p