【bzoj4239】巴士走读 类最短路

       首先发现答案满足二分性质(并不是要去二分QAQ),所以可以排个序然后扫一遍;而且答案只和最后一辆车直接相关,因此需要得到赶上每一辆车i的最晚出发时间g[i]。

       那么要先得到每一个点i,到达点i的最晚出发时间f[i],然后就可以用g[]和f[]互相更新,最后得到所有右端点=n的g[]排序之后更新答案即可。

AC代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define N 100005
using namespace std;

int n,m,pt,cnt,f[N],g[N<<2],ans[N]; struct edg{ int x,y,s,t; }e[N<<2]; struct node{ int x,y; }a[N],c[N<<2];
priority_queue<node,vector<node>,greater<node> > q;
int read(){
	int x=0; char ch=getchar();
	while (ch<'0' || ch>'9') ch=getchar();
	while (ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }
	return x;
}
bool cmp(edg u,edg v){ return u.s<v.s; }
bool operator <(node u,node v){ return u.x<v.x; }
bool operator >(node u,node v){ return u.x>v.x; }
int main(){
	n=read(); m=read(); int i; node t;
	for (i=1; i<=m; i++){
		e[i].x=read(); e[i].y=read(); e[i].s=read(); e[i].t=read();
	}
	sort(e+1,e+m+1,cmp);
	memset(f,-1,sizeof(f)); f[1]=1000000000;
	for (i=1; i<=m; i++){
		while (!q.empty() && q.top().x<=e[i].s){
			t=q.top(); q.pop();
			f[e[t.y].y]=max(f[e[t.y].y],g[t.y]);
		}
		g[i]=min(e[i].s,f[e[i].x]);
		t.x=e[i].t; t.y=i; q.push(t);
		if (e[i].y==n){
			c[++cnt].x=e[i].t; c[cnt].y=g[i];
		}
	}
	sort(c+1,c+cnt+1);
	pt=read();
	for (i=1; i<=pt; i++){
		a[i].x=read(); a[i].y=i;
	}
	sort(a+1,a+pt+1); int now=-1,j=1;
	for (i=1; i<=pt; i++){
		for(; j<=cnt && c[j].x<=a[i].x; j++) now=max(now,c[j].y);
		ans[a[i].y]=now;
	}
	for (i=1; i<=pt; i++) printf("%d\n",ans[i]);
	return 0;
}


by lych

2016.3.25

你可能感兴趣的:(优先队列,最短路)