传送门
Solution
首先我们可以发现,最短路和积水量没有任何的关系,所以我们可以先求出1到全图的最短路。
接下来考虑积水量怎么解决,这相当于是构造一棵最大生成树的(Kruscal)重构树,然后对于一个点(q),显然可以找到可以到达的点,这些点因为(Kruscal)重构树优美的性质,一定会在一个子树内,这时就可以树上倍增+线段树查询了。
Code
/*
mail: mleautomaton@foxmail.com
author: MLEAutoMaton
This Code is made by MLEAutoMaton
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<iostream>
using namespace std;
#define ll long long
#define REP(a,b,c) for(int a=b;a<=c;a++)
#define re register
#define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
inline int gi(){
int f=1,sum=0;char ch=getchar();
while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return f*sum;
}
const int N=800010,Inf=1e9+10;
int front[N],cnt,dis[N],vis[N],n,m,tot,fa[N],rt;
typedef pair<int,int> pii;
#define mp make_pair
vector<pii>G[N],E[N];
priority_queue<pii,vector<pii>,greater<pii> >q;
struct edge{int u,v,l,a;}edg[N];
void dijkstra(){
q.push(mp(0,1));dis[1]=0;
while(!q.empty()){
int u=q.top().second;q.pop();
if(vis[u])continue;vis[u]=1;
for(auto now:G[u]){
int v=now.first,w=now.second;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;q.push(mp(dis[v],v));
}
}
}
}
bool cmp(edge rhs1,edge rhs2){return rhs1.a>rhs2.a;}
int find(int x){if(fa[x]!=x)fa[x]=find(fa[x]);return fa[x];}
void Add(int u,int v,int w){E[u].push_back(mp(v,w));}
void kruscal(){
sort(edg+1,edg+m+1,cmp);
for(int i=1;i<=n;i++)fa[i]=i;tot=n;
for(int i=1;i<=m;i++){
int u=find(edg[i].u),v=find(edg[i].v);
if(u!=v){
int t=++tot;
Add(t,u,edg[i].a);Add(t,v,edg[i].a);
fa[u]=fa[v]=fa[t]=t;
}
}
rt=tot;
}
int f[N][22],mx[N][22],Time,dfn[N],b[N],low[N],t[N<<1];
void dfs(int u,int ff){
f[u][0]=ff;
dfn[u]=++Time;b[Time]=u;
for(auto now:E[u]){
int v=now.first,w=now.second;if(v==ff)continue;
mx[v][0]=w;dfs(v,u);
}
low[u]=Time;
}
int jump(int u,int p){
for(int i=20;~i;i--)
if(f[u][i] && mx[u][i]>p)u=f[u][i];
return u;
}
void build(int o,int l,int r){
if(l==r){t[o]=dis[b[l]];return;}
int mid=(l+r)>>1;
build(o<<1,l,mid);build(o<<1|1,mid+1,r);
t[o]=min(t[o<<1],t[o<<1|1]);
}
int query(int o,int l,int r,int posl,int posr){
if(posl<=l && r<=posr)return t[o];
int mid=(l+r)>>1,ret=Inf;
if(posl<=mid)ret=min(ret,query(o<<1,l,mid,posl,posr));
if(mid<posr)ret=min(ret,query(o<<1|1,mid+1,r,posl,posr));
return ret;
}
void solve();
int main(){
int T=gi();
while(T--)solve();
return 0;
}
void solve(){
memset(front,0,sizeof(front));cnt=0;Time=0;
memset(dis,63,sizeof(dis));memset(vis,0,sizeof(vis));
n=gi();m=gi();
for(int i=1;i<=n;i++)G[i].clear();
for(int i=1;i<=tot;i++)E[i].clear();
for(int i=1;i<=m;i++){
edg[i].u=gi(),edg[i].v=gi(),edg[i].l=gi(),edg[i].a=gi();
G[edg[i].u].push_back(mp(edg[i].v,edg[i].l));
G[edg[i].v].push_back(mp(edg[i].u,edg[i].l));
}
dijkstra();kruscal();
dfs(rt,rt);build(1,1,tot);f[rt][0]=0;
for(int j=1;j<=20;j++)
for(int i=1;i<=tot;i++){
f[i][j]=f[f[i][j-1]][j-1];
mx[i][j]=min(mx[i][j-1],mx[f[i][j-1]][j-1]);
}
int Q=gi(),K=gi(),S=gi(),lastans=0;
while(Q--){
int v=(gi()+1ll*K*lastans%n-1)%n+1,p=(gi()+1ll*K*lastans%(S+1))%(S+1);
v=jump(v,p);
printf("%d
",lastans=query(1,1,tot,dfn[v],low[v]));
}
}