对我这种蒟蒻来说,调了好久好久;
- 先跑dijkstra,求出1号点到所有点的距离。因为是无向图,其实也就是求了所有点到1号点的距离;
- 第二就是kruskal重构树,说起来就是kruskal加边的时候建立一个新 的点,点权就是这条边的边权,就是如图所示;
- 这样有一个好处就是你往上走的时候,经过的点权就是你经过的路径的最大值(可以自行画图看看,我的图巨丑);这样的话你往上走的时候如果需要设置一个最大值,就这样走就好了;
- 然后我们发现时间复杂度凉凉了,所以倍增一波;
- 最后我们统计答案,就是由于重构树中dfs序是连续的,我们进行st表维护区间最小值!!!
代码巨丑陋。。。
#include<bits/stdc++.h>
using namespace std;
typedef pair< int,int > pii;
const int inf=2e9;
const int N=700010;
struct zmk{
int u,v,l,a;
}a[N*3];
struct hyq{
int next,to,va;
}e[N*2];
int head[N],cnt,fa[N],vis[N],lg[N],cas,f[N][21],h[N][21],tot;
int val[N],st[N],b[N],en[N],d[N],root;
int n,m,q,k;
int find(int u){
if(fa[u]==u) return fa[u];
return fa[u]=find(fa[u]);
}
void addedge(int u,int v,int d){
e[++cnt].next=head[u];
e[cnt].to=v;
e[cnt].va=d;
head[u]=cnt;
}
bool cmp(zmk a,zmk b){
return a.a>b.a;
}
void dijkstra(){
d[1]=0;
priority_queue< pii,vector<pii>,greater<pii> > q;
q.push(make_pair(d[1],1));
while(!q.empty()){
int u=q.top().second;
q.pop();
if(vis[u]) continue;
vis[u]=1;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(d[v]>d[u]+e[i].va){
d[v]=d[u]+e[i].va;
q.push(make_pair(d[v],v));
}
}
}
}
void kruskal(){
for(int i=1;i<=m;i++){
val[i+n]=a[i].a;
int sa=find(a[i].u),sb=find(a[i].v);
if(sa!=sb){
addedge(i+n,sa,0);
addedge(i+n,sb,0);
fa[sa]=i+n;
fa[sb]=i+n;
}
}
}
void dfs(int u){
st[u]=++tot;
b[tot]=u;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
f[v][0]=u;
dfs(v);
}
en[u]=tot;
}
void init(){
f[root][0]=0;
for(int j=1;j<=20;j++)
for(int i=1;i<=n+m;i++){
f[i][j]=f[f[i][j-1]][j-1];
}
for(int i=1;i<=tot;i++){
if(b[i]<=n) h[i][0]=d[b[i]];
else h[i][0]=inf;
}
for(int j=1;j<=20;j++)
for(int i=1;i<=tot-(1<<j)+1;i++){
h[i][j]=min(h[i][j-1],h[i+(1<<(j-1))][j-1]);
//cout<<h[i][j]<<" ";
}
}
int query(int l,int r){
int t=lg[r-l+1];
return min(h[l][t],h[r-(1<<t)+1][t]);
}
int main(){
for (int i = 2; i < 700000; i++)
lg[i] = lg[i >> 1] + 1;
scanf("%d",&cas);
while(cas--){
tot=cnt=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) head[i]=0;
for(int i=1;i<=m;i++){
scanf("%d%d%d%d",&a[i].u,&a[i].v,&a[i].l,&a[i].a);
addedge(a[i].u,a[i].v,a[i].l);
addedge(a[i].v,a[i].u,a[i].l);
}
for(int i=1;i<=n;i++){
d[i]=inf;
vis[i]=0;
}
dijkstra();
cnt=0;
for(int i=1;i<=n+m;i++) head[i]=0;
sort(a+1,a+m+1,cmp);
for(int i=1;i<=n+m;i++) fa[i]=i;
for(int i=1;i<=n;i++) val[i]=inf;
kruskal();
root=find(1);
dfs(root);
//for(int i=1;i<=tot;i++) cout<<st[i]<<" "<<en[i]<<"***"<<endl;
init();
int smax;
scanf("%d%d%d",&q,&k,&smax);
int ans = 0;
while(q--){
int v , p;
scanf("%d%d",&v,&p);
if(k){
v=(v+ans-1)%n+1;
p=((long long)p+ans)%(smax+1);
}
for(int i=20;i>=0;i--){
if(val[f[v][i]]>p){
v=f[v][i];
}
}
printf("%d\n",ans=query(st[v],en[v]));
}
}
}
代码很长还没什么用