洛谷P4768/LOJ2718/UOJ393[NOI2018]归程(Dijkstra+kruskal重构树+倍增)
首先要知道$kruskal$重构树:在跑$kruskal$的过程中,把选出来的边建虚点,和两个联通块的根相连,很明显最后得到一个二叉堆。
在这个二叉堆上倍增出最远能跑多高,在这个子树里求出最小的$d_u$即可
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int N=200050; const int M=400050; char rB[1<<21],*S,*T,wB[1<<21]; int wp=-1; inline char gc(){return S==T&&(T=(S=rB)+fread(rB,1,1<<21,stdin),S==T)?EOF:*S++;} inline void flush(){fwrite(wB,1,wp+1,stdout);wp=-1;} inline void pc(char c){if(wp+1==(1<<21))flush();wB[++wp]=c;} inline int rd(){ char c=gc(); while(c<48||c>57)c=gc(); int x=c&15; for(c=gc();c>=48&&c<=57;c=gc())x=(x<<3)+(x<<1)+(c&15); return x; } short buf[15]; inline void wt(int x){ short l=-1; while(x>9){ buf[++l]=x%10; x/=10; } pc(x|48); while(l>=0)pc(buf[l--]|48); pc('\n'); } int G[N],to[M<<1],w[M<<1],nxt[M<<1],sz,d[N],pa[N<<1],lc[N<<1],rc[N<<1],V[N<<1],f[18][N<<1],dep[N<<1],minn[N<<1],n; struct edge{ int u,v,w,p; }a[M]; struct node{ int p,d; node(){} node(int p,int d):p(p),d(d){} inline bool operator <(const node &b)const{return d>b.d;} }; priority_queue<node> Q; inline bool cmp(edge a,edge b){return a.p>b.p;} inline void add(int u,int v,int c){ to[++sz]=v;w[sz]=c;nxt[sz]=G[u];G[u]=sz; to[++sz]=u;w[sz]=c;nxt[sz]=G[v];G[v]=sz; } int gf(int x){return pa[x]==x?x:pa[x]=gf(pa[x]);} void dfs(int u,int fa){ dep[u]=dep[f[0][u]=fa]+1; for(short i=1;(1<<i)<dep[u];++i)f[i][u]=f[i-1][f[i-1][u]]; if(u>n){ dfs(lc[u],u);dfs(rc[u],u); minn[u]=min(minn[lc[u]],minn[rc[u]]); }else minn[u]=d[u]; } inline int work(int u,int p){ for(short i=17;i>=0;--i)if(dep[u]-(1<<i)>0&&V[f[i][u]]>p)u=f[i][u]; return minn[u]; } int main(){ int T=rd(),m,q,s,i,u,v,lans,tot,x,y; bool k; node h; while(T--){ tot=n=rd();m=rd(); memset(G,0,sizeof(G));lans=sz=0; for(i=1;i<=m;++i){ a[i].u=rd();a[i].v=rd();a[i].w=rd();a[i].p=rd(); add(a[i].u,a[i].v,a[i].w); } for(i=2;i<=n;++i)d[i]=2000000001; Q.push(node(1,d[1]=0)); while(!Q.empty()){ h=Q.top();Q.pop(); if(h.d>d[u=h.p])continue; for(i=G[u];i;i=nxt[i])if(d[u]+w[i]<d[v=to[i]])Q.push(node(v,d[v]=d[u]+w[i])); } for(i=1;i<(n<<1);++i)pa[i]=i; sort(a+1,a+m+1,cmp); for(i=1;i<=m;++i)if((x=gf(a[i].u))!=(y=gf(a[i].v))){ pa[x]=++tot;pa[y]=tot; lc[tot]=x;rc[tot]=y; V[tot]=a[i].p; if(tot==(n<<1)-1)break; } dfs(tot,0); q=rd();k=rd();s=rd(); while(q--){ x=(rd()+k*lans-1)%n+1;y=(rd()+k*lans)%(s+1); wt(lans=work(x,y)); } } flush(); return 0; }