最短路
和正解的做法不一样,不过都是 O((q+n)logm) 的。
我的做法:也是最短路。把巴士看成点,并拆成入点和出点,边权为y-x(走它的意义是坐了这个巴士)。对于每一个原图的点u,把所有从这里出去的巴士按x排序,x小的前一辆i-1的入点向后一辆i的入点连边,边权x[i]-x[i-1](走它的意义是去考虑坐i号巴士并消耗等车时间)。把每一辆进入u的巴士的出点连向所有离开u的巴士中x恰好大于它的y的巴士的入点,边权为出去的那辆巴士的y-进入的那辆巴士的x(走它的意义是换车的等车时间)。跑最短路之后在s的出边二分即可。
正解(贴PO爷原文,戳我查看原文):将二元组<站点,时间>看做一个点,那么点数是O(m)的 ,每辆巴士连一条边,每个点向下一个时间连边,然后将所有边反向 ,枚举终点站的每一个时间,加入队列广搜,得到最晚多久到达1号站点可以在这个时间到达终点站,然后对于每个询问去数组中二分即可
好气啊,不知道怎么的刚开始偏大数据拍WA了,后来代码没改重新拍又拍不WA了,交上去居然A了。。。呵呵呵呵
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#include<queue>
#define N 600005
using namespace std;
namespace runzhe2000
{
int read()
{
int r = 0; char c = getchar();
for(; c < '0' || c > '9'; c = getchar());
for(; c >='0' && c <='9'; c = getchar()) r=r*10+c-'0';
return r;
}
const int INF = 1<<28;
int n, m, last[N], ecnt, dis[N], T;
bool vis[N];
vector<int> in[N], out[N];
struct edge{int next, to, val;}e[N<<1];
struct Bus{int a, b, x, y;}bus[N];
struct item{int x, dis;};
bool operator < (item a, item b) {return a.dis > b.dis;}
bool cmp(int i1, int i2){return bus[i1].x < bus[i2].x;}
void addedge(int a, int b, int c){e[++ecnt] = (edge){last[a], b, c}; last[a] = ecnt;}
int pack(int i, int j){return i*2+j;}
void dijkstra()
{
memset(dis, 63, sizeof(dis));
priority_queue<item> q;
q.push((item){T, dis[T] = 0});
for(; !q.empty(); )
{
int x = q.top().x; q.pop();
if(vis[x])continue; vis[x] = 1;
for(int i = last[x]; i; i = e[i].next)
{
int y = e[i].to;
if(dis[x] + e[i].val < dis[y])
q.push((item){y, dis[y] = dis[x] + e[i].val});
}
}
}
void main()
{
n = read(), m = read();
for(int i = 1; i <= m; i++)
{
bus[i].a = read(), bus[i].b = read(), bus[i].x = read(), bus[i].y = read();
out[bus[i].a].push_back(i);
in[bus[i].b].push_back(i);
addedge(pack(i, 1), pack(i, 0), bus[i].y - bus[i].x);
}
for(int i = 1; i <= n; i++)
out[i].push_back(0);
bus[0].x = INF, bus[0].y = INF+INF;
for(int i = 1; i < n; i++)
{
sort(out[i].begin(), out[i].end(), cmp);
for(int j = 0; j < (int)in[i].size(); j++)
{
int u = in[i][j], l = 0, r = (int)out[i].size()-1;
for(; l < r; )
{
int mid = (l+r)>>1;
if(bus[out[i][mid]].x >= bus[u].y) r = mid;
else l = mid+1;
}
addedge(pack(out[i][l], 0), pack(u, 1), bus[out[i][l]].x - bus[u].y);
}
for(int j = 1; j < (int)out[i].size(); j++)
addedge(pack(out[i][j], 0), pack(out[i][j-1], 0), bus[out[i][j]].x - bus[out[i][j-1]].x);
}
T = pack(m+1,0);
for(int i = 0; i < (int)in[n].size(); i++)
addedge(T, pack(in[n][i], 1), 0);
dijkstra();
for(int i = 0; i < (int)out[1].size(); i++)
dis[pack(out[1][i], 0)] += bus[out[1][i]].x;
for(int Q =read(), t; Q--; )
{
t = read();
int l = 0, r = out[1].size() - 1;
for(; l < r; )
{
int mid = (l+r+1)>>1;
if(dis[pack(out[1][mid], 0)] <= t) l = mid;
else r = mid - 1;
}
if(dis[pack(out[1][l], 0)] <= t) printf("%d\n",bus[out[1][l]].x);
else puts("-1");
}
}
}
int main()
{
runzhe2000::main();
}