zoukankan      html  css  js  c++  java
  • [NOI2014]魔法森林

    lct模板题。把所有的边按照a排个序,然后挨个加进去,然后以b为边权,求一个动态最小生成树。把每条边想成一个点,嵌在两个端点之间,然后每次加边的时候判一下新边的两个端点连不连通,连通的话就找两点路径上的权值最大的那个"边点"上的点权,把它和两端点cut了,然后再link这个"边点"和两个点。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N=100005;
    int ch[N][2],fa[N],mx[N],U[N],V[N],W[N],tot;
    bool rev[N];
    inline void pushup(int x) {
        mx[x]=x;
        if(W[mx[ch[x][0]]]>W[mx[x]]) mx[x]=mx[ch[x][0]];
        if(W[mx[ch[x][1]]]>W[mx[x]]) mx[x]=mx[ch[x][1]];
    }
    inline void pushdown(int x) {
        if(rev[x]) 
            swap(ch[x][0],ch[x][1]),
            rev[ch[x][1]]^=1,
            rev[ch[x][0]]^=1,
            rev[x]=0;
    }
    inline bool is_rt(int x) {
        return x!=ch[fa[x]][0]&&x!=ch[fa[x]][1];
    }
    inline bool ck(int x) {
        return x==ch[fa[x]][1];
    }
    inline void rotate(int x) {
        int f=fa[x],ff=fa[f];
        if(!is_rt(f)) ch[ff][ck(f)]=x;
        bool tag=ck(x);
        ch[f][tag]=ch[x][tag^1];
        fa[ch[f][tag]]=f;
        ch[x][tag^1]=f;
        fa[f]=x;
        fa[x]=ff;
        pushup(f);pushup(x);
    }
    int top,stk[N];
    inline void splay(int x) {
        stk[top=1]=x;
        for(int i=x;!is_rt(i);i=fa[i]) stk[++top]=fa[i];
        while(top) pushdown(stk[top--]);
        for(int f;!is_rt(x);rotate(x)) 
            if(!is_rt(f=fa[x]))rotate(ck(x)==ck(f)?f:x);
    }
    inline void access(int x) {
        for(int t=0;x;t=x,x=fa[x]) 
            splay(x),ch[x][1]=t,pushup(x);
    }
    inline void makeroot(int x) {
        access(x);
        splay(x);
        rev[x]^=1;
    }
    inline int findroot(int x) {
        access(x);splay(x);
        while(ch[x][0]) x=ch[x][0];
        return x;
    }
    inline void link(int x,int y) {
        makeroot(x);
        fa[x]=y;
    }
    inline void cut(int x,int y) {
        makeroot(x);access(y);splay(y);
        ch[y][0]=fa[x]=0;
    }
    inline void connect(int x,int y,int v) {
        if(findroot(x)!=findroot(y)) {W[++tot]=v;U[tot]=x;V[tot]=y;link(U[tot],tot);link(V[tot],tot);return;}
        makeroot(x);access(y);splay(y);
        int a=mx[y];
        if(W[a]<=v) return;
        cut(a,U[a]);cut(a,V[a]);
        W[a]=v;
        link(U[a]=x,a);link(V[a]=y,a);
    }
    inline int query(int x,int y) {
        if(findroot(x)!=findroot(y)) return 19260817;
        makeroot(x);access(y);splay(y);
        return W[mx[y]];
    }
    int n,m;
    struct Edge{int u,v,a,b;}e[N];
    bool cmp(Edge x,Edge y) {
        return x.a<y.a;
    }
    int main() {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++) scanf("%d%d%d%d",&e[i].u,&e[i].v,&e[i].a,&e[i].b);
        sort(e+1,e+1+m,cmp);
        tot=n;
        int ans=19260817;
        for(int i=1;i<=m;i++) {
            connect(e[i].u,e[i].v,e[i].b);
            ans=min(ans,query(1,n)+e[i].a);
        }
        if(ans==19260817) puts("-1");
        else cout<<ans;
    }
    魔法森林
    我是咸鱼。转载博客请征得博主同意Orz
  • 相关阅读:
    Codeforces Round #747 比赛记录(vp)
    神秘姿势:把 K(2n) 分解成 2n-1 组完美匹配
    Codeforces Round #745 比赛记录(vp)
    NOIP Camp #2 比赛记录
    数论 专题整理
    Java基础之流程控制语句
    Java基本类型
    开启学科模式
    Strange Queries (莫队+容斥原理)
    洛谷P1993 小K的农场
  • 原文地址:https://www.cnblogs.com/sdfzhsz/p/9708293.html
Copyright © 2011-2022 走看看