题目 N<=2e5 M<=4e5 Q<=4e5;
思路:从点v出发走海拔超过p的边。就是kruskal重构树了。先dijksta处理每个节点到出发点1的最短路d[]. 然后dfs建立fa[][]数组时顺便求出每个节点所掌管的子节点以及他自己 离出发点1最近的节点。这里有些要注意。 if(d[son[y]]<d[son[x]]) son[x]=son[y]…记住这个把。。。
//P4768归程(kruskal重构树倍增+dijkstra预处理+dfs时预处理哪个子节点最近) //q次询问: 给点u,p u只能跑跑边长>p的边 只能走路 问回到1点最少走多少? N<=2e5 M<=4e5 Q<=4e5; #include<bits/stdc++.h> #define m(a,b) memset(a,b,sizeof a) using namespace std; typedef long long ll; const int N=2e5+5,M=4e5+5,K=20; const ll INF=(ll)(1)<<(ll)(61); struct _Edge{int u,v,l,w;}e[M]; inline int cmp(_Edge x,_Edge y){return x.w>y.w;} struct Edge{int to,nex;}edge[N<<1];int head[N<<1],tot; inline void add(int from,int to){ edge[++tot]=(Edge){to,head[from]};head[from]=tot; } struct Edg{int to,len,nex;}edg[M<<1];int hed[N],ttt; inline void ad(int from,int to,int len){ edg[++ttt]=(Edg){to,len,hed[from]};hed[from]=ttt; edg[++ttt]=(Edg){from,len,hed[to]};hed[to]=ttt; } int f[N<<1],val[N],node; inline int seek(int x){return (x==f[x])?x:(f[x]=seek(f[x]));} int n,m; void ex_kruskal(){ for(int i=1;i<=n;++i) f[i]=i; sort(e+1,e+m+1,cmp); int cnt=0;node=n; for(int i=1;i<=m;++i){ int u=e[i].u,v=e[i].v,fu,fv; fu=seek(u),fv=seek(v); if(fu==fv) continue; val[(++node)-n]=e[i].w,++cnt; f[node]=node,f[fu]=node,f[fv]=node; add(node,fu),add(node,fv); if(cnt==(n-1)) break; } } priority_queue<pair<int,int> >q;ll d[N<<1]; void dijkstra(int s){ for(int i=1;i<=2*n;++i) d[i]=INF;//也要初始化[n+1,2*n]. d[s]=0,q.push(make_pair(0,s)); while(!q.empty()){ int x=q.top().second;q.pop(); for(int i=hed[x];i;i=edg[i].nex){ int y=edg[i].to,l=edg[i].len; if(d[y]>d[x]+l){d[y]=d[x]+l,q.push(make_pair(-d[y],y));} } } } int dep[N<<1],fa[N<<1][K+5],son[N<<1]; void dfs(int x){ for(int j=1;(1<<j)<=dep[x];j++) fa[x][j]=fa[fa[x][j-1]][j-1]; son[x]=x; for(int i=head[x];i;i=edge[i].nex){ int y=edge[i].to; dep[y]=dep[x]+1,fa[y][0]=x; dfs(y); if(d[son[y]]<d[son[x]]) son[x]=son[y]; } } inline int BZ(int x,ll w){ for(int j=K;j>=0;j--) if(fa[x][j]!=-1&&val[fa[x][j]-n]>w) x=fa[x][j]; return x; } void init(){ m(head,0),tot=0,m(hed,0),ttt=0; m(fa,-1); for(int i=1;i<=2*n;++i) son[i]=i; } int main(){ int T;scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m);init(); for(int i=1;i<=m;++i) scanf("%d%d%d%d",&e[i].u,&e[i].v,&e[i].l,&e[i].w),ad(e[i].u,e[i].v,e[i].l); ex_kruskal(); dijkstra(1);fa[node][0]=node,dep[node]=0,dfs(node); int q,k,s;scanf("%d%d%d",&q,&k,&s);ll las=0; while(q--){ int v;ll p;scanf("%d%lld",&v,&p); v=(v+k*las-1)%n+1,p=(p+k*las)%(s+1); v=BZ(v,p);printf("%lld\n",las=d[son[v]]); } } }