zoukankan      html  css  js  c++  java
  • 【BZOJ 3669】 [Noi2014]魔法森林 LCT维护动态最小生成树

    这道题看题意是在求一个二维最小瓶颈路,唯一可行方案就是枚举一维在这一维满足的条件下使另一维最小,那么我们就把第一维排序利用A小的边在A大的情况下仍成立来动态加边维护最小生成树。

    #include <cstdio>
    #include <algorithm>
    namespace Pre{
      inline void read(int &sum){
        register char ch=getchar();
        for(sum=0;ch<'0'||ch>'9';ch=getchar());
        for(;ch>='0'&&ch<='9';sum=(sum<<1)+(sum<<3)+ch-'0',ch=getchar());
      }
      const int N=50010;
      const int M=100010;
      const int Inf=0x7f7f7f7f;
      int A[M],B[M],ans=Inf,X[M],Y[M],n,m,e[M];
      inline bool comp(int a,int b){
        return A[a]<A[b];
      }
      inline int Max(int x,int y){
        return x>y?x:y;
      }
      inline int Min(int x,int y){
        return x<y?x:y;
      }
    }
    namespace LCT{
      const int MN=150020;
      struct Node{
        Node *ch[2],*f;
        int id,rid;
        bool rev;
        inline void pushup(){
          using Pre::B;
          id=B[ch[0]->id]>B[ch[1]->id]?ch[0]->id:ch[1]->id;
          id=B[id]>B[rid]?id:rid;
        }
        inline void pushdown();
      }null[MN];
      inline void Swap(Node *&a,Node *&b){
        Node *c=a;
        a=b;
        b=c;
      }
      inline void Node:: pushdown(){
        if(!rev)return;
        Swap(ch[0],ch[1]);
        ch[0]->rev^=1;
        ch[1]->rev^=1;
        rev=0;
      }
      inline void Init(){
        using namespace Pre;
        null->ch[0]=null->ch[1]=null->f=null;
        for(int i=1;i<=n;i++)
          null[i].ch[0]=null[i].ch[1]=null[i].f=null,null[i].id=null[i].rid=0;
        for(int i=n+1;i<=n+m;i++)
          null[i].ch[0]=null[i].ch[1]=null[i].f=null,null[i].id=null[i].rid=i-n;
      }
      inline int get(Node *p){
        return p->f->ch[1]==p;
      }
      inline bool isroot(Node *p){
        return p->f->ch[0]!=p&&p->f->ch[1]!=p;
      }
      inline void rotate(Node *p){
        Node *fa=p->f,*pa=fa->f;
        int j=get(p);
        if(!isroot(fa))pa->ch[get(fa)]=p;
        if((fa->ch[j]=p->ch[j^1])!=null)fa->ch[j]->f=fa;
        fa->f=p;
        p->ch[j^1]=fa;
        p->f=pa;
        fa->pushup();
        p->pushup();
      }
      inline void spaly(Node *p){
        p->pushdown();
        for(Node *fa=p->f;!isroot(p);rotate(p),fa=p->f)
          if(!isroot(fa)){
            fa->f->pushdown(),fa->pushdown(),p->pushdown();
            rotate(get(fa)==get(p)?fa:p);
          }else
            fa->pushdown(),p->pushdown();
      }
      inline void expose(Node *p){
        Node *y=null;
        while(p!=null){
          spaly(p);
          p->ch[1]=y;
          p->pushup();
          y=p;
          p=p->f;
        }
      }
      inline void make_root(Node *p){
        expose(p);
        spaly(p);
        p->rev^=1;
      }
      inline Node *find_root(Node *p){
        expose(p);
        spaly(p);
        while(p->ch[0]!=null)
          p=p->ch[0],p->pushdown();
        return p;
      }
      inline void link(Node *a,Node *b){
        make_root(a);
        a->f=b;
      }
      inline void cut(Node *a,Node *b){
        make_root(a);
        expose(b);
        spaly(b);
        b->ch[0]->f=null;
        b->ch[0]=null;
        b->pushup();
      }
      inline void Link(int a,int b){
        link(null+a,null+b);
      }
      inline void Cut(int a,int b){
        cut(null+a,null+b);
      }
      inline int find(int x){
        return find_root(null+x)-null;
      }
      inline int query(int a,int b){
        Node *x=null+a,*y=null+b;
        make_root(x);
        expose(y);
        spaly(y);
        return Pre::B[y->id];
      }
      inline int query_id(int a,int b){
        Node *x=null+a,*y=null+b;
        make_root(x);
        expose(y);
        spaly(y);
        return y->id;
      }
    }
    inline void Init(){
      using namespace Pre;
      read(n),read(m);
      for(int i=1;i<=m;i++)
        read(X[i]),read(Y[i]),read(A[i]),read(B[i]),e[i]=i;
      std::sort(e+1,e+m+1,comp);
      LCT::Init();
    }
    inline void Work(){
      using namespace Pre;
      using LCT::find;
      using LCT::query;
      using LCT::Link;
      using LCT::Cut;
      using LCT::query_id;
      for(int i=1;i<=m;i++)
        if(find(X[e[i]])!=find(Y[e[i]])){
          Link(e[i]+n,X[e[i]]),Link(e[i]+n,Y[e[i]]);
          if(find(1)==find(n))
            ans=Min(query(1,n)+A[e[i]],ans);
        }else if(query(X[e[i]],Y[e[i]])>B[e[i]]){
          int temp=query_id(X[e[i]],Y[e[i]]);
          Cut(temp+n,X[temp]),Cut(temp+n,Y[temp]);
          Link(e[i]+n,X[e[i]]),Link(e[i]+n,Y[e[i]]);
          if(find(1)==find(n))
            ans=Min(ans,query(1,n)+A[e[i]]);
        }
    }
    int main(){
      using namespace Pre;
      Init(),Work();
      printf("%d",ans==Inf?-1:ans);
      return 0;
    }
  • 相关阅读:
    Saltstack module apache 详解
    Saltstack module ip 详解
    Saltstack module iosconfig 详解
    Saltstack module introspect 详解
    Saltstack module inspector 详解
    Saltstack module ini 详解
    Saltstack module incron 详解
    Modbus 指令 RS485指令规则
    停车系统对接第三方在线支付平台(二)
    停车系统对接第三方在线支付平台
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7341114.html
Copyright © 2011-2022 走看看