zoukankan      html  css  js  c++  java
  • 【Luogu】P4234最小差值生成树(LCT)

      题目链接

      能把LCT打得每个函数都恰有一个错误也是挺令我惊讶的。

      本题使用LCT维护生成树,具体做法是对原图中的每个边建一个点,然后连边的时候相当于是将边的起点跟“边”这个点连起来,边的终点也跟它连起来。

      放个图。

      

      比如这是原边。

      然后我们搞成这样。

      

      那个小点就是原来那条边啦。

      然后我们要连边的时候就连成这样

      

      比如小点的编号为new,我们就要link(from,new),link(to,new)

      切掉的时候就cut(from,new)cut(to,new)。

      之后呢,我们令splay的每个节点维护以自己为根的splay中连的权值最小的边是哪条,这样连成一个环的时候我们就可以很方便的把环中最小的那个边切掉,就可以维护啦

      

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<cctype>
    #include<queue>
    #define maxn 500000
    using namespace std;
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    struct Edge{
        int from,to,val;
        bool operator <(const Edge a){
            return val<a.val;
        }
    }edge[maxn];
    
    bool cmp(Edge a,Edge b){    return a.val<b.val;    }
    int stack[maxn],top;
    
    struct Splay{
        struct Node{
            int e[2],fa,val,mini,tag,id;
        }tree[maxn];
        inline int iden(int x){    return x==tree[tree[x].fa].e[1];    }
        inline bool isroot(int x){    return x!=tree[tree[x].fa].e[0]&&x!=tree[tree[x].fa].e[1];    }
        inline void update(int x){
            tree[x].mini=tree[x].id;
            if(edge[tree[tree[x].e[0]].mini].val<edge[tree[x].mini].val)    tree[x].mini=tree[tree[x].e[0]].mini;
            if(edge[tree[tree[x].e[1]].mini].val<edge[tree[x].mini].val)    tree[x].mini=tree[tree[x].e[1]].mini;
        }
        inline void connect(int x,int fa,int how){    tree[x].fa=fa;    tree[fa].e[how]=x;    }
        inline void reverse(int x){
            swap(tree[x].e[0],tree[x].e[1]);
            tree[x].tag^=1;
        }
        inline void pushdown(int x){
            if(tree[x].tag==0)    return;
            if(tree[x].e[0])    reverse(tree[x].e[0]);
            if(tree[x].e[1])    reverse(tree[x].e[1]);
            tree[x].tag=0;
        }
        void rotate(int x){
            int y=tree[x].fa,r=tree[y].fa;
            int sony=iden(x),sonr=iden(y);
            tree[x].fa=r;    if(!isroot(y))    tree[r].e[sonr]=x;
            int b=tree[x].e[sony^1];
            connect(b,y,sony);
            connect(y,x,sony^1);
            update(y);
        }
        inline void pushto(int x){
            top=0;
            while(!isroot(x)){
                stack[++top]=x;
                x=tree[x].fa;
            }
            pushdown(x);
            while(top){
                int from=stack[top--];
                pushdown(from);
            }
        }
        inline void splay(int x){
            pushto(x);
            while(!isroot(x)){
                if(!isroot(tree[x].fa))
                    if(iden(x)==iden(tree[x].fa))    rotate(tree[x].fa);
                    else rotate(x);
                rotate(x);
            }
            update(x);
        }
        void access(int x){
            int last=0;
            while(x){
                splay(x);
                tree[x].e[1]=last;
                update(x);
                last=x;    x=tree[x].fa;
            }
            return;
        }
        inline void makeroot(int x){
            access(x);
            splay(x);
            reverse(x);
        }
        inline void split(int x,int y){
            makeroot(x);
            access(y);
            splay(y);
        }
        inline void link(int x,int y){
            split(x,y);
            tree[x].fa=y;
        }
        inline void cut(int x,int y){
            split(x,y);
            if(tree[y].e[0]!=x||tree[x].e[1])    return;
            tree[x].fa=tree[y].e[0]=0;
        }
        inline int findroot(int x){
            access(x);
            splay(x);
            while(tree[x].e[0])    x=tree[x].e[0];
            return x;
        }
    }s;
    
    bool vis[maxn];
    
    int main(){
        int n=read(),m=read();
        for(int i=1;i<=m;++i)    edge[i]=(Edge){read(),read(),read()};
        sort(edge+1,edge+m+1,cmp);    edge[0].val=0x7fffffff;
        for(int i=1;i<=m;++i){
            s.tree[i+n].val=edge[i].val;
            s.tree[i+n].id=i;
        }
        int cnt=0,now=1;
        int ans=0x7fffffff;
        for(int i=1;i<=m;++i){
            int from=edge[i].from,to=edge[i].to,val=edge[i].val;
            if(from==to){
                vis[i]=1;
                continue;
            }
            //printf("D");
            if(s.findroot(from)==s.findroot(to)){
                s.split(from,to);
                int mini=s.tree[to].mini;
                //printf("%d>>>>
    ",mini);
                s.cut(edge[mini].from,mini+n);
                s.cut(edge[mini].to,mini+n);
                vis[mini]=1;
                cnt--;
            }
            
            s.link(from,i+n);    s.link(to,i+n);
            cnt++;
            if(cnt>=n-1){
                while(vis[now])    now++;//printf("S");
                ans=min(ans,val-edge[now].val);
            }
            
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    Hihocoder 1275 扫地机器人 计算几何
    CodeForces 771C Bear and Tree Jumps 树形DP
    CodeForces 778D Parquet Re-laying 构造
    CodeForces 785E Anton and Permutation 分块
    CodeForces 785D Anton and School
    CodeForces 785C Anton and Fairy Tale 二分
    Hexo Next 接入 google AdSense 广告
    如何统计 Hexo 网站的访问地区和IP
    Design and Implementation of Global Path Planning System for Unmanned Surface Vehicle among Multiple Task Points
    通过ODBC接口访问人大金仓数据库
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8778364.html
Copyright © 2011-2022 走看看