洛谷P4768/LOJ2718/UOJ393[NOI2018]归程

首先要知道$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;
}
View Code

猜你喜欢

转载自www.cnblogs.com/sunshine-chen/p/11258903.html