显然,我们可以将询问按照规定时间从小到大排序,依次处理.
那么我们显然要求合法的点中从 $n$ 号点出发到达点 $i$ 的最迟时间,我们令这个为 $f[i]$
而 $f[i]$ 显然可以用最短路来求.
如果求 $n$ 次最短路的话显然超时,但是我们可以对于每一个节点所连边排序,然后每次枚举之前没有扩展过的边.
这样就能保证每条边恰好被扩展一次,时间复杂度正确.
code:
#include <bits/stdc++.h> #define N 200004 #define inf 1000000004 #define setIO(s) freopen(s".in","r",stdin) using namespace std; int cur,n,m; int f[N],done[N],tag[N],ans[N]; struct Node { int u,dis; Node(int u=0,int dis=0):u(u),dis(dis){} bool operator<(Node b) const { return b.dis>dis; } }; struct ask { int id,tim; ask(int id=0,int tim=0):id(id),tim(tim){} }as[N]; struct edge { int to,st,ed; edge(int to=0,int st=0,int ed=0):to(to),st(st),ed(ed){} }; bool cmp_as(ask a,ask b) { return a.tim<b.tim; } bool cmp(edge a,edge b) { return a.ed<b.ed; } vector<edge>G[N]; priority_queue<Node>q; void dij() { while(!q.empty()) { Node e=q.top(); q.pop(); int u=e.u; if(done[u]==cur) continue; done[u]=cur; for(int i=tag[u];i<G[u].size();++i,++tag[u]) { if(G[u][i].ed>f[u]) break; int v=G[u][i].to; if(f[v]<G[u][i].st) { f[v]=G[u][i].st; q.push(Node(v,f[v])); } } } } void solve(int t) { f[n]=t; q.push(Node(n,f[n])); dij(); } int main() { // setIO("input"); int i,j; scanf("%d%d",&n,&m); for(i=1;i<=m;++i) { int a,b,x,y; scanf("%d%d%d%d",&a,&b,&x,&y); G[b].push_back(edge(a,x,y)); } memset(f,-1,sizeof(f)); f[n]=0; for(i=1;i<=n;++i) { sort(G[i].begin(),G[i].end(),cmp); } int Q; scanf("%d",&Q); for(i=1;i<=Q;++i) { as[i].id=i; scanf("%d",&as[i].tim); } sort(as+1,as+1+Q,cmp_as); for(i=1;i<=Q;++i) { cur=i; solve(as[i].tim); ans[as[i].id]=f[1]; } for(i=1;i<=Q;++i) printf("%d ",ans[i]); return 0; }