zoukankan      html  css  js  c++  java
  • bzoj 2816: [ZJOI2012]网络 (LCT 建多棵树)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2816

    题面: http://www.lydsy.com/JudgeOnline/upload/zjoi2012.pdf

    思路:

    因为c很小,我们可以建c棵树,然后跑LCT。

    实现代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int M = 3e5+10;
    const int inf = 0x3f3f3f3f;
    
    struct node{
        int u,v;
    };
    int a[M];
    int col[M][11];
    bool operator < (node a,node b){
        if(a.u == b.u) return a.v < b.v;
        return a.u < b.u;
    }
    map<node,int>mp;
    struct lct{
    int c[M][2],fa[M],val[M],sum[M],rev[M],st[M];
    inline void up(int x){
        int l = c[x][0],r = c[x][1];
        sum[x] = max(max(sum[l],sum[r]),val[x]);
    }
    
    inline void pushrev(int x){
        int t = c[x][0];
        c[x][0] = c[x][1]; c[x][1] = t;
        rev[x] ^= 1;
    }
    
    inline void pushdown(int x){
        if(rev[x]){
            int l = c[x][0],r = c[x][1];
            if(l) pushrev(l);
            if(r) pushrev(r);
            rev[x] = 0;
        }
    }
    
    inline bool nroot(int x){  //判断一个点是否为一个splay的根
        return c[fa[x]][0]==x||c[fa[x]][1] == x;
    }
    
    inline void rotate(int x){
        int y = fa[x],z = fa[y],k = c[y][1] == x;
        int w = c[x][!k];
        if(nroot(y)) c[z][c[z][1]==y]=x;
        c[x][!k] = y; c[y][k] = w;
        if(w) fa[w] = y; fa[y] = x; fa[x] = z;
        up(y);
    }
    
    inline void splay(int x){
        int y = x,z = 0;
        st[++z] = y;
        while(nroot(y)) st[++z] = y = fa[y];
        while(z) pushdown(st[z--]);
        while(nroot(x)){
            y = fa[x];z = fa[y];
            if(nroot(y))
                rotate((c[y][0]==x)^(c[z][0]==y)?x:y);
            rotate(x);
        }
        up(x);
    }
    
    //打通根节点到指定节点的实链,使得一条中序遍历从根开始以指定点结束的splay出现
    inline void access(int x){
        for(int y = 0;x;y = x,x = fa[x])
            splay(x),c[x][1]=y,up(x);
    }
    
    inline void makeroot(int x){  //换根,让指定点成为原树的根
        access(x); splay(x); pushrev(x);
    }
    
    inline int findroot(int x){  //寻找x所在原树的树根
        access(x); splay(x);
        while(c[x][0]) pushdown(x),x = c[x][0];
        splay(x);
        return x;
    }
    
    inline void split(int x,int y){  //拉出x-y的路径成为一个splay
        makeroot(x); access(y); splay(y);
    }
    
    inline void cut(int x,int y){   //断开边
        makeroot(x);
        if(findroot(y) == x&&fa[y] == x&&!c[y][0]){
            fa[y] = c[x][1] = 0;
            up(x);
        }
    }
    
    inline void link(int x,int y){   //连接边
        makeroot(x);
        if(findroot(y)!=x) fa[x] = y;
    }
    }LCT[11];
    int main()
    {
        int n,m,c,k;
        scanf("%d%d%d%d",&n,&m,&c,&k);
        for(int i = 1;i <= n;i ++) scanf("%d",&a[i]);
        for(int i = 1;i <= n;i ++){
            for(int j = 1;j <= c;j ++){
                LCT[j].val[i] = a[i];
            }
        }
        int u,v,w;
        for(int i = 1;i <= m;i ++){
            scanf("%d%d%d",&u,&v,&w); w++;
            mp[(node){u,v}] = w;
            mp[(node){v,u}] = w;
            col[u][w]++; col[v][w]++;
            LCT[w].link(u,v);
        }
        int op,x,y;
        while(k--){
            scanf("%d",&op);
            if(op == 0){
                scanf("%d%d",&x,&y); a[x] = y;
                for(int i = 1;i <= c;i ++){
                    LCT[i].splay(x);
                    LCT[i].val[x] = a[x];
                }
            }
            else if(op == 1){
                scanf("%d%d%d",&u,&v,&w); w++;
                int f = mp[(node){u,v}];
                if(!f) {
                    printf("No such edge.
    ");
                    continue;
                }
                if(f == w){
                    printf("Success.
    ");
                    continue;
                }
                if(col[u][w]>1||col[v][w]>1){
                    printf("Error 1.
    "); continue;
                }
                if(LCT[w].findroot(u)==LCT[w].findroot(v)){
                    printf("Error 2.
    "); continue;
                }
                col[u][f]--; col[v][f]--;
                col[u][w]++; col[v][w]++;
                mp[(node){u,v}] = w;
                mp[(node){v,u}] = w;
                LCT[f].cut(u,v);
                LCT[w].link(u,v);
                printf("Success.
    ");
            }
            else{
                scanf("%d%d%d",&w,&u,&v); w++;
                if(LCT[w].findroot(u)!=LCT[w].findroot(v)){
                    printf("-1
    "); continue;
                }
                LCT[w].split(u,v);
                printf("%d
    ",LCT[w].sum[v]);
            }
        }
    }
  • 相关阅读:
    2018-4-17-软件设计-白话依赖注入
    2018-2-13-wpf-PreviewTextInput-在鼠标输入获得-_u0003
    2018-5-23-为何-987654321_123456789-的值是-8.0000000729
    寄存器位写操作
    Linux多IP配置
    Kconfig和Makefile
    linux设置网卡速率
    Winmanager,NERDTree和MiniBufExplorer
    SuperTab
    ping
  • 原文地址:https://www.cnblogs.com/kls123/p/10792350.html
Copyright © 2011-2022 走看看