传送门
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\n",lastans=query(1,1,tot,dfn[v],low[v])); } }