zoukankan      html  css  js  c++  java
  • bzoj3669: [Noi2014]魔法森林

    LCT.

    将边按a从小到大排序后不断往进加,出现环就把b最大的边去除掉。

    lct中边也要单独建一个节点保存边权。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn = 200000 + 10;
    const int maxm = 800000 + 10;
    const int inf = 0x7f7f7f7f;
    
    struct BCJ {
        int f[maxn];
        
        int find(int x) {
            return f[x]==x?x:f[x]=find(f[x]);
        }
        
        void combine(int u,int v) {
            int ru=find(u),rv=find(v);
            f[rv]=ru;
        }
        
        int query(int u,int v) {
            int ru=find(u),rv=find(v);
            return ru==rv;
        }
        
        BCJ() {for(int i=1;i<maxn;i++) f[i]=i;}    
    }bcj;
    
    struct LCT {
        int l[maxn],r[maxn],f[maxn];
        int mb[maxn],b[maxn],stack[maxn],sp;
        bool root[maxn],rev[maxn];
        
        void reverse(int x) {
            rev[x]^=1;    
        }
        
        void push(int x) {
            if(rev[x]) {
                swap(l[x],r[x]);
                rev[l[x]]^=1;
                rev[r[x]]^=1;
                rev[x]=0;
            }
        }
        
        void push_route(int x) {
            sp=0;
            while(!root[x]) {
                stack[++sp]=x;
                x=f[x];
            }
            stack[++sp]=x;
            for(int i=sp;i>=1;i--) push(stack[i]);
        }
        
        void update(int x) {
            mb[x]=x;
            if(b[mb[l[x]]]>b[mb[x]]) mb[x]=mb[l[x]];
            if(b[mb[r[x]]]>b[mb[x]]) mb[x]=mb[r[x]];     
        }
        
        void lr(int x) {
            int y=f[x];
            r[y]=l[x];
            if(l[x]) f[l[x]]=y;
            f[x]=f[y];
            if(root[y]) {root[x]=1; root[y]=0;}
            else if(l[f[y]]==y) l[f[y]]=x;
            else r[f[y]]=x;
            f[y]=x;
            l[x]=y;
            update(y);
            update(x);
        }
        
        void rr(int x) {
            int y=f[x];
            l[y]=r[x];
            if(r[x]) f[r[x]]=y;
            f[x]=f[y];
            if(root[y]) {root[x]=1; root[y]=0;}
            else if(l[f[y]]==y) l[f[y]]=x;
            else r[f[y]]=x;
            f[y]=x;
            r[x]=y;
            update(y);
            update(x);
        }
        
        void rotate(int x) {
            if(l[f[x]]==x) rr(x);
            else lr(x);
        }
        
        void splay(int x) {
            push_route(x);
            while(!root[x]) {
                if(root[f[x]]) rotate(x);
                else if((l[f[x]]==x)==(l[f[f[x]]]==f[x])) {rotate(f[x]); rotate(x);}
                else {rotate(x); rotate(x);}
            }
        }
        
        void access(int x) {
            for(int y=0;x;x=f[y=x]) {
                splay(x);
                root[r[x]]=1;
                root[r[x]=y]=0;
                update(x);
            }
        }
        
        void cut(int x,int y) {
            access(x);
            splay(x);
            reverse(x);
            access(y);
            splay(y);
            f[x]=l[y]=0;
            root[x]=1;
        }
        
        void link(int x,int y) {
            access(x);
            splay(x);
            reverse(x);
            f[x]=y;
        }
        
        int query(int x,int y) {
            access(x);
            splay(x);
            reverse(x);
            access(y);    
            splay(y);
            return mb[y];
        }
        
        int& operator [] (int x) {
            return b[x];
        }
        
        LCT() {
            for(int i=0;i<maxn;i++) {
                root[i]=1; b[i]=-inf; mb[i]=i;
            }
        }
    }lct;
    
    struct Edge {
        int u,v,a,b;
        
        void init() {
            scanf("%d%d%d%d",&u,&v,&a,&b);
        }
            
    }e[maxm];
    
    bool cmp(Edge a,Edge b) {
        return a.a<b.a || (a.a==b.a && a.b<b.b);    
    }
    
    int n,m,res=inf;
    
    int main() {
        //freopen("ex_forest3.out","w",stdout);    
        //freopen("ex_forest3.in","r",stdin);
    
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++) e[i].init();
        sort(e+1,e+m+1,cmp);
        
        for(int i=1,bq;i<=m;i++) {
            if(bcj.query(e[i].u,e[i].v)) {
                bq=lct.query(e[i].u,e[i].v);
                if(lct[bq]>e[i].b) {
                    lct.cut(e[bq-n].u,bq);
                    lct.cut(e[bq-n].v,bq);
                    lct[i+n]=e[i].b;
                    lct.link(e[i].u,i+n);
                    lct.link(e[i].v,i+n);
                }
            }
            else {
                bcj.combine(e[i].u,e[i].v);
                lct[i+n]=e[i].b;
                lct.link(e[i].u,i+n);
                lct.link(e[i].v,i+n);
            }
            
            if(bcj.query(1,n)) {
                res=min(res,lct[lct.query(1,n)]+e[i].a);
            }
        }
        printf("%d
    ",res<inf?res:-1);
        return 0;
    }
  • 相关阅读:
    Hello World
    函数
    js基础
    html
    npm
    数据库
    前端了解的简要php
    模块
    scrapy爬虫
    php升级代码检查
  • 原文地址:https://www.cnblogs.com/invoid/p/5640322.html
Copyright © 2011-2022 走看看