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;
}
原文地址:https://www.cnblogs.com/invoid/p/5640322.html