• NOI 2014 魔法森林(BZOJ 3669) 题解


    对边按a权值排序,按b权值建LCT,按排序后的顺序依次加边。如果加边后形成环则删除环上最大的边。如果起点终点联通则更新答案。

      1 #include<cstdio>
      2 #include<algorithm>
      3 #define rep(i,n) for(int i=0;i<n;++i)
      4 const int MAXN=50000+5;
      5 const int MAXM=100000+5;
      6 const int INF=~0U>>1;
      7 struct Node{
      8     int mxv,v;
      9     Node* p,*ch[2],*mx;
     10     int e;
     11     bool rev;
     12     Node() {mxv=v=-1;}
     13     inline bool d() const
     14     {
     15         return p->ch[1]==this;
     16     }
     17     inline void revIt()
     18     {
     19         rev^=1;
     20         std::swap(ch[0],ch[1]);
     21     }
     22     inline void setc(Node* t,bool d)
     23     {
     24         ch[d]=t;
     25         t->p=this;
     26     }
     27     inline void maintain()
     28     {
     29         mxv=v;mx=this;
     30         rep(i,2) if(ch[i]->mxv>mxv)
     31         {
     32             mxv=ch[i]->mxv;
     33             mx=ch[i]->mx;
     34         }
     35     }
     36     inline bool isRoot() const;
     37     inline void pushdown();
     38 }Tnull,*null=&Tnull;
     39 inline bool Node::isRoot() const
     40 {
     41     return p==null || (p->ch[0]!=this && p->ch[1]!=this);
     42 }
     43 inline void Node::pushdown()
     44 {
     45     if(rev)
     46     {
     47         rev=0;
     48         rep(i,2) if(ch[i]!=null)
     49             ch[i]->revIt();
     50     }
     51 }
     52 inline void rot(Node* t)
     53 {
     54     Node* p=t->p;
     55     p->pushdown();t->pushdown();
     56     bool d=t->d();
     57     if(!p->isRoot()) p->p->setc(t,p->d());
     58     else t->p=p->p;
     59     p->setc(t->ch[d^1],d);
     60     t->setc(p,d^1);
     61     p->maintain();
     62 }
     63 inline void splay(Node* t)
     64 {
     65     t->pushdown();
     66     while(!t->isRoot())
     67     {
     68         if(t->p->isRoot()) rot(t);
     69         else t->d()==t->p->d()?(rot(t->p),rot(t)):(rot(t),rot(t));
     70     }
     71     t->maintain();
     72 }
     73 inline void access(Node* u)
     74 {
     75     for(Node* v=null;u!=null;v=u,u=u->p)
     76     {
     77         splay(u);
     78         u->setc(v,1);
     79         u->maintain();
     80     }
     81 }
     82 inline void makeRoot(Node* u)
     83 {
     84     access(u);
     85     splay(u);
     86     u->revIt();
     87 }
     88 inline void link(Node* u,Node* v)
     89 {
     90     makeRoot(u);u->p=v;
     91 }
     92 inline void cut(Node* u,Node* v)
     93 {
     94     makeRoot(u);
     95     access(v);
     96     splay(v);
     97     if(v->ch[0]==u)
     98     {
     99         v->setc(null,0);
    100         v->maintain();
    101         u->p=null;
    102     }
    103 }
    104 inline Node* find(Node* u)
    105 {
    106     for(;u->p!=null;u=u->p);
    107     return u;
    108 }
    109 inline void change(Node* u,int v)
    110 {
    111     access(u);
    112     splay(u);
    113     u->v=v;
    114     u->maintain();
    115 }
    116 inline void getMax(Node* u,Node* v,int& maxv,int& e,Node*& mx)
    117 {
    118     makeRoot(u);
    119     access(v);
    120     splay(v);
    121     maxv=v->mxv;
    122     mx=v->mx;
    123     e=v->mx->e;
    124 }
    125 inline int query(Node* u,Node* v)
    126 {
    127     makeRoot(u);
    128     access(v);
    129     splay(v);
    130     return v->mxv;
    131 }
    132 Node mem[MAXN+MAXM],*C=mem;
    133 inline Node* newNode(int v,int e)
    134 {
    135     C->p=C->ch[0]=C->ch[1]=null;
    136     C->rev=0;
    137     C->v=C->mxv=v;
    138     C->mx=C;
    139     C->e=e;
    140     return C++;
    141 }
    142 struct Edge{
    143     int u,v,a,b;
    144     Edge() {}
    145     Edge(int u,int v,int a,int b):u(u),v(v),a(a),b(b) {}
    146     bool operator<(const Edge& rhs) const
    147     {
    148         return a<rhs.a;
    149     }
    150 }edges[MAXM];
    151 Node* pt[MAXN+MAXM];
    152 int n,m;
    153 int ans=INF;
    154 int main()
    155 {
    156     //freopen("1.in","r",stdin);
    157     scanf("%d%d",&n,&m);
    158     rep(i,m)
    159     {
    160         int u,v,a,b;
    161         scanf("%d%d%d%d",&u,&v,&a,&b);
    162         edges[i]=Edge(u,v,a,b);
    163     }
    164     std::sort(edges,edges+m);
    165     rep(i,n) pt[i+1]=newNode(0,-1);
    166     rep(i,m) pt[i+n+1]=newNode(edges[i].b,i);
    167     rep(i,m)
    168     {
    169         Edge e=edges[i];
    170         if(find(pt[e.u])!=find(pt[e.v])) link(pt[e.u],pt[i+n+1]),link(pt[e.v],pt[i+n+1]);
    171         else
    172         {
    173             int en,maxv;
    174             Node* mx;
    175             getMax(pt[e.u],pt[e.v],maxv,en,mx);
    176             if(maxv>e.b)
    177             {
    178                 cut(pt[edges[en].u],pt[en+n+1]);
    179                 cut(pt[edges[en].v],pt[en+n+1]);
    180                 link(pt[e.u],pt[i+n+1]);
    181                 link(pt[e.v],pt[i+n+1]);
    182             }
    183         }
    184         if(find(pt[1])==find(pt[n])) ans=std::min(ans,query(pt[1],pt[n])+edges[i].a);
    185     }
    186     printf("%d
    ",ans==INF?-1:ans);
    187     return 0;
    188 }
    View Code
  • 相关阅读:
    <亲测>CentOS7yum安装PHP7.2
    linux开机出现一下错误Give root password for maintenance (or type Control-D to continue):
    解决js输出汉字乱码问题
    <亲测>.NET Core项目在Linux上使用QRCoder时出错"Unable to load DLL 'gdiplus'"
    <亲测>阿里云centos7 挂载数据盘配置
    centos 磁盘清理 /dev/vda1系统盘满了
    两种方式:mysql查看正在执行的sql语句
    adb调试android设备 说的比较清楚的一篇文章
    <亲测>window+iis+letsencrypt+ssl 手动续期(通配符域名)
    申请免费通配符证书(Let's Encrypt)并绑定IIS
  • 原文地址:https://www.cnblogs.com/lowsfish/p/4378758.html
Copyright © 2020-2023  润新知