BZOJ1354: [Baltic2005]Bus Trip

题解:  首先把原图扣除了  原来的边变成点 点权为ci-bi  我们连边时当且仅当x的入边的di小于x的出边的ai是两条线路能连边 这样子的边是m^2的不满足要求 我们考虑建一排虚点  对于x的出边ai排序 这样子对于入边所对应的出边就是一段后缀边 这样边只有o(m)条 所以我们跑一遍最长路dp即可

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=2e5+10;
const double eps=1e-8;
#define ll long long
const ll inf=1e18+7;
using namespace std;
int du[MAXN];
struct edge{int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
int num=0;
void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;du[y]++;num++;}
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return x*f;
}
typedef struct node{
    int id,key;
    friend bool operator<(node aa,node bb){return aa.key<bb.key;}
}node;
int a[MAXN],n,m,p,T;
vector<node>v1[MAXN],v2[MAXN];
queue<int>que;
ll dis[MAXN];
bool vis[MAXN];
vector<int>vec;
void dsu(int t){
    for(int i=0;i<=t;i++)if(!du[i])que.push(i),vec.pb(i);
    while(!que.empty()){
	int t1=que.front();que.pop();
	link(t1){
	    du[j->t]--;
	    if(!du[j->t])que.push(j->t),vec.pb(j->t);
	}
    }
}
void dij(int t){
    for(int i=0;i<=t;i++)dis[i]=-1;
    dis[0]=0;int cnt=1;
    for(int i=0;i<vec.size();i++){
	int v=vec[i];
	if(dis[v]!=-1){
	    link(v){
		if(dis[j->t]<dis[v]+a[j->t]){
		    cnt++;
		    dis[j->t]=dis[v]+a[j->t];
		}
	    }
	}
    }
}
int main(){
    n=read(),m=read(),p=read(),T=read();
    int si,ti,ai,bi,ci,di;
    inc(i,1,m){
    si=read();ti=read();ai=read();bi=read();ci=read();di=read();
    if(di>T)continue;
    a[i]=ci-bi;a[i+m]=0;
    add(i+m,i);
    v1[si].pb((node){i+m,ai});v2[ti].pb((node){i,di});
    }
	v1[p].pb((node){2*m+1,T});v2[1].pb((node){0,0});
	inc(i,1,n)sort(v1[i].begin(),v1[i].end());
	inc(i,1,n)sort(v2[i].begin(),v2[i].end());
    inc(i,1,n){
	int t1=v1[i].size();
	for(int j=1;j<t1;j++)add(v1[i][j-1].id,v1[i][j].id);
    }
    inc(i,1,n){
	int k=0;int sz=v1[i].size();
	for(int j=0;j<v2[i].size();j++){
	    while(k<sz&&v1[i][k].key<v2[i][j].key)k++;
	    if(k!=sz)add(v2[i][j].id,v1[i][k].id);
	}
    }
    dsu(2*m+1);
    dij(2*m+1);
   if(dis[2*m+1]==-1)printf("-1\n");
    else printf("%lld\n",T-dis[2*m+1]);
}

 

1354: [Baltic2005]Bus Trip

Time Limit: 5 Sec  Memory Limit: 162 MB
Submit: 140  Solved: 91
[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

 

posted @ 2018-11-22 23:58  wang9897  阅读(123)  评论(0编辑  收藏  举报