luogu 4234 最小差值生成树 LCT

感觉码力严重下降~

#include <bits/stdc++.h>  
#define N 400006 
#define inf 1000000000     
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std; 
multiset<int>S;    
multiset<int>::iterator it;         
struct Edge 
{
    int u,v,c; 
    Edge(int u=0,int v=0,int c=0):u(u),v(v),c(c){}  
}e[N];
bool cmp(Edge a,Edge b) 
{
    return a.c<b.c;    
}   
struct Union
{
    int p[N];  
    void init() 
    {
        for(int i=1;i<N;++i) p[i]=i; 
    } 
    int find(int x) 
    {
        return p[x]==x?x:p[x]=find(p[x]);     
    }
    int merge(int x,int y) 
    {
        x=find(x),y=find(y); 
        if(x!=y) 
        {
            p[x]=y; 
            return 1; 
        } 
        return 0;            
    }
}ufs;    
struct Link_Cut_Tree
{          
    #define lson t[x].ch[0] 
    #define rson t[x].ch[1]   
    int sta[N];     
    struct Node 
    {      
        int ch[2],f,min,id,val,rev;                          
    }t[N];   
    int isrt(int x) 
    {
        return !(t[t[x].f].ch[0]==x||t[t[x].f].ch[1]==x);       
    }
    int get(int x)                     
    {
        return t[t[x].f].ch[1]==x; 
    }   
    void pushup(int x) 
    {     
        t[x].min=t[x].val, t[x].id=x;     
        if(lson && t[lson].min<t[x].min) t[x].min=t[lson].min,t[x].id=t[lson].id;   
        if(rson && t[rson].min<t[x].min) t[x].min=t[rson].min,t[x].id=t[rson].id;    
    } 
    void mark(int x) 
    { 
        if(x) t[x].rev^=1,swap(lson,rson);     
    }
    void pushdown(int x) 
    {   
        if(t[x].rev) 
        {
            if(lson) mark(lson); 
            if(rson) mark(rson); 
            t[x].rev=0;          
        }
    }
    void rotate(int x) 
    {
        int old=t[x].f,fold=t[old].f,which=get(x);   
        if(!isrt(old)) t[fold].ch[t[fold].ch[1]==old]=x;     
        t[old].ch[which]=t[x].ch[which^1], t[t[old].ch[which]].f=old;  
        t[x].ch[which^1]=old,t[old].f=x,t[x].f=fold;       
        pushup(old),pushup(x);       
    }    
    void splay(int x) 
    {
        int v=0,u=x,fa;            
        for(sta[++v]=u;!isrt(u);u=t[u].f) sta[++v]=t[u].f;      
        for(;v;--v) pushdown(sta[v]);                          
        for(u=t[u].f;(fa=t[x].f)!=u;rotate(x)) 
            if(t[fa].f!=u) 
                rotate(get(fa)==get(x)?fa:x);          
    }
    void Access(int x) 
    {
        for(int y=0;x;y=x,x=t[x].f) 
            splay(x),rson=y,pushup(x);       
    }
    void makeroot(int x) 
    {
        Access(x),splay(x),mark(x);    
    }   
    void link(int x,int y) 
    {
        makeroot(x),t[x].f=y;      
    }   
    void cut(int x,int y) 
    {
        makeroot(x),Access(y),splay(y);   
        t[t[y].ch[0]].f=0;   
        t[y].ch[0]=0;    
        pushup(y);       
    }   
    void split(int x,int y) 
    {
        makeroot(x),Access(y),splay(y);      
    }
    #undef lson 
    #undef rson 
}op;   
int main() 
{ 
    int i,j,n,m,ans=inf;    
    // setIO("input");           
    scanf("%d%d",&n,&m);     
    for(i=1;i<=m;++i) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].c);    
    sort(e+1,e+1+m,cmp);     
    ufs.init();   
    for(i=1;i<=n;++i) op.t[i].val=inf;          
    for(i=1;i<=m;++i) 
    { 
        int x=e[i].u,y=e[i].v,c=e[i].c,_new=i+n;  
        if(x==y) continue;    
        if(ufs.merge(x,y)) 
        {    
            op.t[_new].val=c;       
            op.link(x,_new);   
            op.link(_new,y);   
            S.insert(c);       
        } 
        else
        {
            op.split(x,y);    
            if(op.t[y].min<c)                                                   
            { 
                S.erase(S.find(op.t[y].min));       
                S.insert(c);                                           
                int kk=op.t[y].id;                                
                int xx=e[kk-n].u;       
                int yy=e[kk-n].v;       
                op.cut(xx,kk);  
                op.cut(yy,kk);    
                op.t[_new].val=c;              
                op.link(x,_new);  
                op.link(_new,y);   
            }
        }  
        if(S.size()>=n-1) 
        {
            it=S.end();    
            it--;  
            ans=min(ans,*(it)-*(S.begin()));              
        }
    }     
    printf("%d\n",ans);    
    return 0; 
}

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值