zoukankan      html  css  js  c++  java
  • BZOJ 5415: [Noi2018]归程(kruskal重构树)

    解题思路

      (NOI2018)(Day1) (T1),当时打网络赛的时候不会做。学了一下(kruskal)重构树后发现问题迎刃而解了。根据(kruskal)的性质,如果要找从(u)出发,所走边权(>lim)的所能到达的点,可以将边从大到小排序,重构树后从(u)往上跳到点权(>lim)深度最浅的点,这个点子树的叶节点为所求点集合。有了这个以后就可以跑一遍从(1)开始的最短路,记(Min(i))表示重构树上(i)这个节点所有子树到(1)的最小值。然后对于每次询问,把刚才所说的深度最浅的点找出来,它的(Min)即为答案。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
     
    using namespace std;
    const int N=400005;
    typedef long long LL;
     
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
        while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
        return f?x:-x;
    }
     
    int n,m,q,K,S,w[N],f[N][22],T,val[N<<1];
    int head[N],cnt,to[N<<1],nxt[N<<1],F[N],tot,num;
    LL ans,Min[N];
     
    struct Edge{
        int u,v,a,l;
        friend bool operator<(const Edge A,const Edge B){
            return A.a>B.a;
        }   
    }edge[N];
     
    struct Node{
        int id; LL w;
        friend bool operator<(const Node A,const Node B){
            return A.w>B.w;
        }
        Node(int _id=0,int _w=0) {id=_id; w=_w;}
    };
    priority_queue<Node> Q;
     
    inline void add(int bg,int ed,int w){
        to[++cnt]=ed,nxt[cnt]=head[bg],val[cnt]=w,head[bg]=cnt;
    }
     
    int get(int x){
        if(x==F[x]) return x;
        return F[x]=get(F[x]);
    }
     
    inline void init(){
        tot=num=ans=cnt=0;
        for(int i=1;i<=n;i++) F[i]=i;
        memset(head,0,sizeof(head));
        memset(f,0,sizeof(f));
    }
     
    inline void dijkstra(){
        memset(Min,0x3f,sizeof(Min));
        Q.push(Node(1,0));Min[1]=0; Node now;
        while(Q.size()){
            now=Q.top();Q.pop();
            int x=now.id; if(Min[x]!=now.w) continue;
            for(int i=head[x];i;i=nxt[i]){
                int u=to[i];
                if(Min[x]+val[i]<Min[u]){
                    Min[u]=Min[x]+val[i];
                    Q.push(Node(u,Min[u]));
                }
            }
        }
    }
     
    inline void build(){
        for(int i=1;i<=m;i++){
            edge[i].u=rd(),edge[i].v=rd(),edge[i].l=rd(),edge[i].a=rd();
            add(edge[i].u,edge[i].v,edge[i].l); add(edge[i].v,edge[i].u,edge[i].l);
        }
        dijkstra(); sort(edge+1,edge+1+m); int x,y;
        cnt=0; memset(head,0,sizeof(head)); num=n;
        for(int i=1;i<=m;i++){
            x=get(edge[i].u); y=get(edge[i].v);
            if(x==y) continue;
            num++; F[num]=F[x]=F[y]=num;
            add(num,x,0); add(num,y,0);
            w[num]=edge[i].a; tot++;
            if(tot==n-1) break;
        }
    }
     
    void dfs(int x,int fa){
        f[x][0]=fa;
        for(int i=1;i<=19;i++)
            f[x][i]=f[f[x][i-1]][i-1];
        for(int i=head[x];i;i=nxt[i])
            dfs(to[i],x),Min[x]=min(Min[x],Min[to[i]]);
    }
     
    int query(int x,int lim){
        for(int i=19;~i;i--)
            if(f[x][i] && w[f[x][i]]>lim) x=f[x][i];
        return Min[x];
    }
     
    inline void work(){
        int x=rd(),y=rd();
        x=(x+ans*K%n-1+n)%n+1;
        y=(y+ans*K%(S+1))%(S+1);
        ans=query(x,y);
        printf("%lld
    ",ans);
    }
     
    int main(){
        T=rd();
        while(T--){
            n=rd(),m=rd();
            init(); build(); dfs(num,0);
            q=rd(); K=rd(); S=rd();
            while(q--) work();
        }
        return 0;
    }
    
  • 相关阅读:
    二十三种设计模式 python实现
    python logging的输出
    redis
    Django1.11序列化与反序列化
    Django1.11基础视图
    Django1.11模型类数据库操作
    Django1.11创建
    泛型全面分析和应用(二)
    泛型全面分析和应用(一)
    注解的基本盘点 -- 《Java编程思想》
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/10275522.html
Copyright © 2011-2022 走看看