• BZOJ3732:Network(LCT与最小生成树)


    给你N个点的无向图 (1 <= N <= 15,000),记为:1…N。 
    图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 < = d_j < = 1,000,000,000).
    
    现在有 K个询问 (1 < = K < = 20,000)。 
    每个询问的格式是:A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?
    
    Input
    第一行: N, M, K。 
    第2..M+1行: 三个正整数:X, Y, and D (1 <= X <=N; 1 <= Y <= N). 表示X与Y之间有一条长度为D的边。 
    第M+2..M+K+1行: 每行两个整数A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?
    
    Output
     对每个询问,输出最长的边最小值是多少。
    
    Sample Input
    6 6 8
    1 2 5
    2 3 4
    3 4 3
    1 4 8
    2 5 7
    4 6 2
    1 2
    1 3
    1 4
    2 3
    2 4
    5 1
    6 2
    6 1
    Sample Output
    5
    5
    5
    4
    4
    7
    4
    5
    Hint
    1 <= N <= 15,000 
    
    1 <= M <= 30,000 
    
    1 <= d_j <= 1,000,000,000 
    
    1 <= K <= 15,000

    题意:给定N点M边的无向图,每边有权值,Q次询问,每次询问给出u、v,回答u到v的所有路径中最大边的最小值。

    思路:常识可知,需要最小生成树,然后就是最小生成树两点间的最大值。

    可以用树剖+线段树解决 。或者动态树LCT姿势搞定。

    (写LCT写惯了就不想写树剖了有没有

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn=50010;
    struct egde{
        int x,y,val;
    }e[maxn];
    void read(int &x){
        char c=getchar(); x=0;
        for(;c>'9'||c<'0';c=getchar());
        for(;c<='9'&&c>='0';c=getchar()) x=(x<<3)+(x<<1)+c-'0';
    }
    struct LCT
    {
        int Max[maxn],rev[maxn],ch[maxn][2],fa[maxn],stc[maxn],top;
        int isroot(int x){
            return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
        }
        int get(int x){
            return ch[fa[x]][1]==x;
        }
        void pushdown(int x)
        {
            if(!rev[x]||!x) return ;
            swap(ch[x][0],ch[x][1]);
            if(ch[x][0]) rev[ch[x][0]]^=1; 
            if(ch[x][1]) rev[ch[x][1]]^=1; 
            rev[x]=0;
        }
        void pushup(int x)
        {
            Max[x]=x;
            if(ch[x][0]&&e[Max[ch[x][0]]].val>e[Max[x]].val) Max[x]=Max[ch[x][0]];
            if(ch[x][1]&&e[Max[ch[x][1]]].val>e[Max[x]].val) Max[x]=Max[ch[x][1]];
        }
        void rotate(int x)
        {
            int old=fa[x],fold=fa[old],opt=get(x);
            if(!isroot(old)) ch[fold][get(old)]=x;
            fa[x]=fold;
            ch[old][opt]=ch[x][opt^1]; fa[ch[old][opt]]=old;
            ch[x][opt^1]=old; fa[old]=x; 
            pushup(old); pushup(x);
        }
        void splay(int x)
        {
            int top=0; stc[++top]=x;
            for(int i=x;!isroot(i);i=fa[i]) stc[++top]=fa[i];
            for(int i=top;i;i--) pushdown(stc[i]);
            for(int f;!isroot(x);rotate(x)){
                if(!isroot(f=fa[x]))
                  rotate(get(x)==get(f)?f:x);
            }        
        }
        void access(int x)
        {
            int rson=0;
            for(;x;rson=x,x=fa[x]){
                splay(x);
                ch[x][1]=rson;
                pushup(x);
            }
        }
        int find(int x){ access(x); splay(x); while(ch[x][0]) x=ch[x][0]; return x;}
        int query(int x,int y) { make_root(y); access(x);  splay(x); return Max[x]; }
        void make_root(int x) { access(x); splay(x); rev[x]^=1; }
        void link(int x,int y) { make_root(x); fa[x]=y; splay(x); }
        void cut(int x,int y) { make_root(x); access(y); splay(y); fa[x]=ch[y][0]=0; }    
        
    }S;
    int main()
    {
        int N,M,Q,u,v,i;
        scanf("%d%d%d",&N,&M,&Q);
        for(i=1;i<=M;i++){
             read(e[i].x); read(e[i].y) ;read(e[i].val);
             if(S.find(M+e[i].x)!=S.find(M+e[i].y)){
                 S.link(i,M+e[i].x); S.link(i,M+e[i].y);
             }
             else {
                 int tmp=S.query(M+e[i].x,M+e[i].y);
                 if(e[tmp].val>e[i].val){
                     S.cut(tmp,M+e[tmp].x); S.cut(tmp,M+e[tmp].y);
                     S.link(i,M+e[i].x); S.link(i,M+e[i].y);
                 }
             } 
        }
        while(Q--){
            read(u); read(v);
            printf("%d
    ",e[S.query(M+u,M+v)].val);
        }
        return 0;
    }
  • 相关阅读:
    多任务处理:控制默认行为
    多任务处理:管理调度Executor 接口
    多任务处理:服务器协议
    自己来做服务级的木马后门
    IBM ThinkPad
    韩国地名词汇/ 한국지명어휘(注册跑跑韩服有用)1
    EXE程序的自删除实现
    IBM ThinkPad
    EXE程序的自删除实现
    用VBScript实现对Windows注册表的修改
  • 原文地址:https://www.cnblogs.com/hua-dong/p/8709108.html
Copyright © 2020-2023  润新知