zoukankan      html  css  js  c++  java
  • 洛谷2387 BZOJ3669魔法森林题解

    题目链接

    BZ链接

    这道题被很多人用spfa水了过去,表示很。。。

    其实spfa很好卡,这组数据可以卡掉大多数spfa

    链接:密码:rjvk

    这里讲一下LCT的做法

    我们按照a将边排序,然后依次添加

    每次加入时若两边没有联通,就直接加入,否则就

    检查两边的路径中权值b最大的权值是多少,如果大于当前加入边的权值

    就将该边删掉,然后将当前边加入

    注意lct维护边权时需要用到拆点

    # include<iostream>
    # include<algorithm>
    # include<cmath>
    # include<cstring>
    # include<cstdio>
    using namespace std;
    const int mn = 150005;
    const int inf = 2147483647;
    struct edge{int u,v,a,b;};
    edge e[mn];
    bool cmp(const edge &x,const edge &y)
    {
        if(x.a==y.a) return x.b<y.b;
        else return x.a<y.a;
    }
    int n,m,ans,fa[mn];
    int _find(int x) {return x==fa[x] ? x : fa[x]=_find(fa[x]);}
    struct LCT{
        int val[mn],fa[mn],c[mn][2],mx[mn],st[mn];
        //mx[x]表示子树中权值最大的点的编号
        bool rev[mn];
        bool nroot(int x)
        {
            return c[fa[x]][0]==x || c[fa[x]][1]==x;
        }
        void zhuan(int x)
        {
            swap(c[x][1],c[x][0]);
            rev[x]^=1;
        }
        void pushdown(int x)
        {
            if(rev[x])
            {
                rev[x]=0;
                if(c[x][0]) zhuan(c[x][0]);
                if(c[x][1]) zhuan(c[x][1]);
            }
        }
        void updown(int x)
        {
            mx[x]=x;
            if(c[x][0])
            {
                if(val[mx[c[x][0]]]>val[mx[x]])
                   mx[x]=mx[c[x][0]];
            }
            if(c[x][1])
            {
                if(val[mx[c[x][1]]]>val[mx[x]])
                   mx[x]=mx[c[x][1]];
            }
        }
        void rotate(int x)
        {
            int y=fa[x],z=fa[y],flag;
            if(c[y][0]==x) flag=1;
            else flag=0;
            if(nroot(y))
            {
                if(c[z][0]==y) c[z][0]=x;
                else c[z][1]=x;
            }
            c[y][flag^1]=c[x][flag],fa[c[x][flag]]=y;
            c[x][flag]=y;
            fa[y]=x,fa[x]=z;
            updown(y);
            updown(x);
        }
        void splay(int x)
        {
            int top=0;
            st[++top]=x;
            for(int i=x;nroot(i);i=fa[i])
               st[++top]=fa[i];
            for(;top;top--) pushdown(st[top]);
            while(nroot(x))
            {
                int y=fa[x],z=fa[y];
                if(nroot(y))
                {
                    if((c[y][0]==x) ^ (c[z][0]==y))
                      rotate(x);
                    else rotate(y);
                }
                rotate(x);
            }
            updown(x);
        }
        void access(int x)
        {
           int t=0;
           while(x){splay(x);c[x][1]=t;updown(x);t=x;x=fa[x];}
        }
        void makeroot(int x)
        {
            access(x);
            splay(x);
            zhuan(x);
        }
        void link(int x,int y)
        {
            makeroot(x);
            fa[x]=y;
        }
        void cut(int x,int y)
        {
            makeroot(x);
            access(y);
            splay(y);
            c[y][0]=fa[x]=0;
            updown(y);
        }
        int query(int x,int y)
        {
            makeroot(x);
            access(y);
            splay(y);
            return mx[y];
        }
    }T;
    void pre()
    {
        for(int i=1;i<=n;i++)
          fa[i]=i;
        for(int i=1;i<=m;i++)
          T.val[i+n]=e[i].b;
    }
    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);
        ans=inf;
        pre();
       /* for(int i=1;i<=m;i++)
        printf("%d %d
    ",e[i].a,e[i].b);*/
        for(int i=1;i<=m;i++)
        {
            int x=e[i].u,y=e[i].v;
            int xx=_find(x),yy=_find(y);
            if(xx!=yy)
            {
                fa[xx]=yy;
                T.link(x,i+n);
                T.link(i+n,y);
            }
            else {
                int k=T.query(x,y);
                if(T.val[k]>e[i].b)
                {
                    T.cut(e[k-n].u,k);
                    T.cut(k,e[k-n].v);
                    T.link(x,i+n);
                    T.link(i+n,y);
                }
            }
            if(_find(1)==_find(n))
              ans=min(ans,e[i].a+T.val[T.query(1,n)]);
        //  printf("%d %d
    ",e[i].a,T.query(1,n));
        }
        if(ans==inf) printf("-1");
        else printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    linux命令-ps
    solr参数说明
    CAP原理和BASE思想
    java多线程文件上传服务器
    swift的简介
    浅谈对【OSI七层协议】的理解
    手写简易WEB服务器
    JVM知识整理和学习(转载并修改)
    多线程学习笔记六
    多线程学习笔记五
  • 原文地址:https://www.cnblogs.com/logeadd/p/9367839.html
Copyright © 2011-2022 走看看