题目
https://uoj.ac/problem/393
思路
关于kruskal重构树的blog:https://www.cnblogs.com/zwfymqz/p/9683523.html
这里我们讲一下这题怎么做:
先构出kruskal重构树,显然如果一个节点的水位大于p,子树内任意两点可以不花代价互相到达。
于是我们要求出深度最浅且水位不超过p的点,倍增就行。
然后预处理每个点到1号点的距离,dij
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=8e5+77;
int n,m,cnt;
ll Q,K,S;
struct A
{
int u,v;
ll hi;
}a[N<<1];
bool cmp(A a,A b)
{
return a.hi>b.hi;
}
struct E
{
int v,next;
ll dis;
}e[N<<1];
int ls[N],tot;
ll d[N],vis[N],ff[N];
priority_queue< pair<ll,int> > q;
ll mi[N],val[N];
int g[N][23];
void add(int u,int v,ll dis)
{
e[++tot].next=ls[u];
e[tot].v=v; e[tot].dis=dis;
ls[u]=tot;
}
void dij()
{
memset(vis,0,sizeof(vis));
memset(d,111,sizeof(d)); d[1]=0;
q.push(make_pair(0,1));
while(!q.empty())
{
int u=q.top().second; q.pop();
if(vis[u]) continue;
vis[u]=1;
for(int i=ls[u]; i; i=e[i].next)
{
int v=e[i].v;
if(d[u]+e[i].dis<d[v])
{
d[v]=d[u]+e[i].dis;
q.push(make_pair(-d[v],v));
}
}
}
}
int gf(int x)
{
if(x==ff[x])return x;
else return ff[x]=gf(ff[x]);
}
void dfs(int u)
{
mi[u]=d[u];
for(int i=ls[u]; i; i=e[i].next)
{
int v=e[i].v;
g[v][0]=u;
dfs(v);
mi[u]=min(mi[u],mi[v]);
}
}
void kruskal()
{
memset(ls,0,sizeof(ls)); tot=1;
sort(a+1,a+1+m,cmp);
for(int i=1; i<=n; i++)ff[i]=i;
for(int i=1; i<=m; i++)
{
int fu=gf(a[i].u),fv=gf(a[i].v);
if(fu!=fv)
{
val[++cnt]=a[i].hi;
ff[fu]=ff[fv]=ff[cnt]=cnt;
add(cnt,fu,0); add(cnt,fv,0);
}
}
dfs(cnt);
}
void init()
{
memset(ls,0,sizeof(ls)); tot=1;
memset(g,0,sizeof(g));
memset(mi,111,sizeof(mi));
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
init();
scanf("%d%d",&n,&m);cnt=n;
for(int i=1; i<=m; i++)
{
int u,v,dis,hi;
scanf("%d%d%d%d",&u,&v,&dis,&hi);
add(u,v,dis); add(v,u,dis);
a[i].u=u; a[i].v=v; a[i].hi=hi;
}
dij(); kruskal();
for(int i=1; (1<<i)<=cnt; i++)
for(int u=1; u<=cnt; u++) g[u][i]=g[g[u][i-1]][i-1];
scanf("%lld%lld%lld",&Q,&K,&S);
ll last=0;
while(Q--)
{
int vi,pi;
scanf("%d%d",&vi,&pi);
vi=(vi+K*last-1)%n+1;
pi=(pi+K*last)%(S+1);
for(int j=22;j>=0;--j)
if(g[vi][j]&&val[g[vi][j]]>pi)
vi=g[vi][j];
printf("%lld\n",last=mi[vi]);
}
}
return 0;
}