【bzoj1354: [Baltic2005]Bus Trip】图论+动态规划

1354: [Baltic2005]Bus Trip

Time Limit: 5 Sec   Memory Limit: 162 MB
Submit: 121   Solved: 86
[ Submit][ Status][ Discuss]

Description

这里有 N 座城镇, 和城镇之间的 M 巴士单行线(没有中间停靠站)。 城镇从1到N 标号。 一个旅行者在 0时刻位于 1号城镇想要到达 P 号城镇。他将乘坐巴士在T 时刻到达P 号城镇。如果他早到了,他必须等待。
对于任意一个巴士路线i, 我们知道其中的起点城镇si 和目标城镇ti 。我们也同样知道路线的出发时间和到达时间,但仅仅是近似值:我们知道巴士离开起点城镇si 在时间范围[ai, bi]内,且到达目标城镇ti 在时间范围[ci, di]内(端点值包括在内)。
旅行者不喜欢等待, 因此他要寻找一个旅行计划使得最大等待时间尽量小,同时保证绝对不会错过计划中的任何一辆巴士(意思是, 每次他换乘巴士, 他需要下车的巴士的最晚到达时间不会迟于他需要搭乘的下一辆巴士的最早出发时间)。
当计算等待时间时,我们必须假设最早可能到达的时间和最晚可能出发的时间。
编写一个程序,寻找一个最为合理的搭车计划。

Input

The input file name is TRIP.IN. The first line contains the integer numbers N (1<=N<=50,000), M (1<=M<=100,000), P ( 1<=P<=N), and T (0<=T<=1,000,000,000).
The following M lines describe the bus routes. Each line contains the integer numbers si, ti, ai, bi, ci, di, where si and ti are the source and destination towns of the bus route i, and ai, bi, ci, di describe the departure and arrival times as explained above (1<=si<=N, 1<=ti<=N, 0<=ai<=bi < ci<=di<=1,000,000,000).

Output

只需要包含一个数——最合理搭车方案的最长可能等待时间。如果不可能保证在T 时刻到达城市P,那么输出-1。

Sample Input

3 6 2 100
1 3 10 20 30 40
3 2 32 35 95 95
1 1 1 1 7 8
1 3 8 8 9 9
2 2 98 98 99 99
1 2 0 0 99 101

Sample Output

32



对于一条巴士路径,必须占用的时间为[a[i],d[i]],而乘坐的时间为[b[i],c[i]] ,若是去掉a[i],d[i]的限制,我们只要连上c[i]-b[i]的边,再跑最长路,最后输出 T-最长路 就是最后的答案了。那么加上a[i]和d[i]的限制呢?

因为占用的时间是[a[i],d[i]],至少要a[i]到达,所以要用第i条边来更新的话,我们要保存a[i]之前的s点的信息,到d[i]的时候,我们再用之前保存的s点的信息来更新t点。

也就是把一条边拆边,将a[i]和d[i]分离,再从小到大排序,按此顺序来进行操作,当当前做到的是a[i]的时刻,我们保存s点的信息,直到到d[i]时刻的时候,我们用a[i]的时刻保存的s点的信息来更新t点。就这样跑最长路(也就是动规)就可以求解了。

#include<cstdio>
#include<algorithm>
#define N 200005
#define INF 2e9
using namespace std;
struct he{
	int s,t,a,b,c,p;
}b[N];
int dis[N],f[N],n,m,P,T,cnt;
bool cmp(he a,he b){
	if(a.a==b.a) return (a.p&1)>(b.p&1);
	return a.a<b.a;
}
void work(){
	for(int i=1;i<=n;i++) dis[i]=-INF;
		dis[1]=0;
	 	for(int i=1;i<=cnt;i++)
		 if(b[i].a<=T){
		 if(b[i].p&1){
		 	if(f[b[i].p/2]+b[i].c-b[i].b>dis[b[i].t]) {
		 		dis[b[i].t]=f[b[i].p/2]+b[i].c-b[i].b;
		 	}
		 }else{
		 	f[b[i].p/2]=dis[b[i].s];
		 }
		}else break;
		if(dis[P]<0) printf("-1\n");
		else printf("%d\n",T-dis[P]);
}
int main(){
	freopen("1.in","r",stdin);
	freopen("1.out","w",stdout);
	scanf("%d%d%d%d",&n,&m,&P,&T);
	for(int i=1;i<=m;i++){
		cnt++;
		scanf("%d%d%d%d%d%d",&b[cnt].s,&b[cnt].t,&b[cnt].a,&b[cnt].b,&b[cnt].c,&b[cnt+1].a);
		b[cnt+1].s=b[cnt].s;b[cnt+1].t=b[cnt].t;
		b[cnt+1].b=b[cnt].b;b[cnt+1].c=b[cnt].c;
		b[cnt].p=i*2;b[cnt+1].p=i*2+1;cnt++;
	}
//	for(int i=1;i<=cnt;i++)
//	 printf("%d %d %d %d %d %d \n",b[i].s,b[i].t,b[i].a,b[i].b,b[i].c,b[i].p);
	sort(b+1,b+1+cnt,cmp);
	work(); 
}


©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页