• Luogu P4234 最小差值生成树


    题意

    给定一个 (n) 个点 (m) 条边的有权无向图,求出原图的一棵生成树使得该树上最大边权与最小边权的差值最小。

    ( exttt{Data Range:}1leq nleq 5 imes 10^4,1leq mleq 2 imes 10^5,1leq wleq 5 imes 10^4)

    题解

    这位傻逼把 (n) 个节点的树所含有的边的数目认为是 (n),还在出现环的时候立即统计答案(可能生成树都没构建出来),导致 ( exttt{WA}) 了一发又一发,请大家不要学他。

    直接进入正题。

    考虑先将边权从小到大排序,然后一条一条的考虑。

    如果这条边加入当前的图中不会成环的话,那么直接加进来即可。

    如果成了环的话,考虑在环上删去边权最小的边。

    为什么这么做是正确的呢?

    假设我们现在考虑的是第 (k) 条边,连接 (u_i)(v_i),边权为 (w_i),讨论一下当前图中边权最小的边的位置。

    • 当这条边的位置在环上的时候,由于新图的边权最小值改变了,所以需要更新答案。

    • 当这条边的位置不在环上的时候,对答案无影响。

    所以我们每一次需要更新答案的时候我们都进行了更新,自然答案就是对的了。

    加入完这条边之后,如果当前的图是原图的一棵生成树的话那么更新一下答案就好了。

    注意到整个过程涉及到删边和连边操作,所以采用 ( exttt{LCT}) 来维护生成树。

    更新答案时,由于要找到最小边权的边的位置,并且每一次加完边之后最小边权的边的位置单调不降(因为排过序了),打标记+移动指针就可以了。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef int ll;
    typedef long long int li;
    const ll MAXN=3e5+51;
    struct Edge{
        ll from,to,dist;
        inline bool operator <(const Edge &rhs)const
        {
            return dist<rhs.dist;
        }
    };
    ll n,m,ptr=1,cur,x,y,offset=60000,res;
    Edge ed[MAXN];
    ll ffa[MAXN],vis[MAXN];
    inline ll read()
    {
        register ll num=0,neg=1;
        register char ch=getchar();
        while(!isdigit(ch)&&ch!='-')
        {
            ch=getchar();
        }
        if(ch=='-')
        {
            neg=-1;
            ch=getchar();
        }
        while(isdigit(ch))
        {
            num=(num<<3)+(num<<1)+(ch-'0');
            ch=getchar();
        }
        return num*neg;
    }
    inline ll find(ll x)
    {
        return x==ffa[x]?x:ffa[x]=find(ffa[x]);
    }
    namespace LCT{
        struct Node{
            ll fa,mn,val,rv,sz;
            ll ch[2];
        };
        struct LinkCutTree{
            Node nd[MAXN];
            ll st[MAXN];
            #define ls nd[x].ch[0]
            #define rs nd[x].ch[1]
            inline bool nroot(ll x)
            {
                return nd[nd[x].fa].ch[0]==x||nd[nd[x].fa].ch[1]==x;
            }
            inline ll get(ll x,ll y)
            {
                return nd[x].val<nd[y].val?x:y;
            }
            inline void update(ll x)
            {
                nd[x].mn=get(x,get(nd[ls].mn,nd[rs].mn));
            }
            inline void reverse(ll x)
            {
                swap(ls,rs),nd[x].rv^=1;
            }
            inline void spread(ll x)
            {
                if(nd[x].rv)
                {
                    ls?reverse(ls):(void)(1),rs?reverse(rs):(void)(1);
                    nd[x].rv=0;
                }
            }
            inline void rotate(ll x)
            {
                ll fa=nd[x].fa,gfa=nd[fa].fa;
                ll dir=nd[fa].ch[1]==x,son=nd[x].ch[!dir];
                if(nroot(fa))
                {
                    nd[gfa].ch[nd[gfa].ch[1]==fa]=x;
                }
                nd[x].ch[!dir]=fa,nd[fa].ch[dir]=son;
                if(son)
                {
                    nd[son].fa=fa;
                }
                nd[fa].fa=x,nd[x].fa=gfa,update(fa);
            }
            inline void splay(ll x)
            {
                ll fa=x,gfa,cur=0;
                st[++cur]=fa;
                while(nroot(fa))
                {
                    st[++cur]=fa=nd[fa].fa;
                }
                while(cur)
                {
                    spread(st[cur--]);
                }
                while(nroot(x))
                {
                    fa=nd[x].fa,gfa=nd[fa].fa;
                    if(nroot(fa))
                    {
                        rotate((nd[fa].ch[0]==x)^(nd[gfa].ch[0]==fa)?x:fa);
                    }
                    rotate(x);
                }
                update(x);
            }
            inline void access(ll x)
            {
                for(register int i=0;x;x=nd[i=x].fa)
                {
                    splay(x),rs=i,update(x);
                }
            }
            inline void makeRoot(ll x)
            {
                access(x),splay(x),reverse(x);
            }
            inline void split(ll x,ll y)
            {
                makeRoot(x),access(y),splay(y);
            }
            inline void link(ll x)
            {
                makeRoot(ed[x].from);
                nd[nd[ed[x].from].fa=x+offset].fa=ed[x].to;
                nd[x+offset].val=ed[x].dist,update(x);
            }
            inline void cut(ll x)
            {
                access(ed[x-offset].from),splay(x);
                ls=rs=nd[ls].fa=nd[rs].fa=0,update(x);
            }
            #undef ls
            #undef rs
        };
    }
    LCT::LinkCutTree lct;
    int main()
    {
        n=read(),m=read();
        for(register int i=1;i<=m;i++)
        {
            ed[i].from=read(),ed[i].to=read(),ed[i].dist=read();
        }
        for(register int i=0;i<=n;i++)
        {
            ffa[i]=i,lct.nd[i].val=0x7fffffff;
        }
        sort(ed+1,ed+m+1);
        for(register int i=1;i<=m;i++)
        {
            if(find(x=ed[i].from)!=find(y=ed[i].to))
            {
                vis[i]=1,lct.link(i),cur++,ffa[ffa[y]]=ffa[x];
                if(cur==n-1)
                {
                    res=ed[i].dist-ed[ptr].dist;
                }
            }
            else
            {
                if(x==y)
                {
                    continue;
                }
                lct.split(x,y),vis[lct.nd[y].mn-offset]=0;
                lct.cut(lct.nd[y].mn),lct.link(i),vis[i]=1;
                while(!vis[ptr])
                {
                    ptr++;
                }
                if(cur==n-1)
                {
                    res=min(res,ed[i].dist-ed[ptr].dist);
                }
            }
        }
        printf("%d
    ",res);
    }
    
  • 相关阅读:
    Hanoi塔
    采药
    进制转换(大数)
    Load Balancing with NGINX 负载均衡算法
    upstream模块实现反向代理的功能
    epoll
    在nginx启动后,如果我们要操作nginx,要怎么做呢 别增加无谓的上下文切换 异步非阻塞的方式来处理请求 worker的个数为cpu的核数 红黑树
    粘性会话 session affinity sticky session requests from the same client to be passed to the same server in a group of servers
    负载均衡 4层协议 7层协议
    A Secure Cookie Protocol 安全cookie协议 配置服务器Cookie
  • 原文地址:https://www.cnblogs.com/Karry5307/p/13062494.html
Copyright © 2020-2023  润新知