zoukankan      html  css  js  c++  java
  • 3669 [Noi2014]魔法森林(LCT,最小生成树)

    【题目链接】

        http://www.lydsy.com/JudgeOnline/problem.php?id=3669

    【题意】

        给定一个无向图,求1-n的路径中最小的max{ai}+max{bi}

    【思路】

        将边按照a排序。LCT维护关于b的最小生成树。

        顺序枚举每条边u,v,如果u,v已经连接则比较u,v路径上的最大边与新边,否则直接相连。

        如果1与n连通,则用e.a+max{e.b}更新ans。直观地看,最小生成树上的max{e.b}是1..i条边加入后能够得到的最小b。

        _max的初值赋-1,即保证maxe存在,否则无限TLE

    【代码】

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<iostream>
      4 #include<algorithm>
      5 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
      6 using namespace std;
      7 
      8 typedef long long ll;
      9 const int N = 1e5+10;
     10 
     11 ll read() {
     12     char c=getchar();
     13     ll f=1,x=0;
     14     while(!isdigit(c)) {
     15         if(c=='-') f=-1; c=getchar();
     16     }
     17     while(isdigit(c))
     18         x=x*10+c-'0',c=getchar();
     19     return x*f;
     20 }
     21 
     22 struct Edge {
     23     int u,v,a,b;
     24     bool operator < (const Edge& rhs) const {
     25         return a<rhs.a;
     26     }
     27 }e[N<<1];
     28 int en;
     29 void adde(int u,int v,int a,int b)
     30 {
     31     e[++en]=(Edge){u,v,a,b};
     32 }
     33 
     34 namespace LCT {
     35 
     36     struct Node {
     37         int rev,v,maxe;
     38         Node *ch[2],*fa;
     39         Node() {}
     40         Node(int x) ;
     41         void reverse() {
     42             rev^=1;
     43             swap(ch[0],ch[1]);
     44         }
     45         void up_push() {
     46             if(fa->ch[0]==this||fa->ch[1]==this)
     47                 fa->up_push();
     48             if(rev) {
     49                 ch[0]->reverse();
     50                 ch[1]->reverse();
     51                 rev=0;
     52             }
     53         }
     54         void maintain() {
     55             int _max=-1;
     56             if(e[ch[0]->maxe].b>_max)
     57                 _max=e[ch[0]->maxe].b,maxe=ch[0]->maxe;
     58             if(e[ch[1]->maxe].b>_max)
     59                 _max=e[ch[1]->maxe].b,maxe=ch[1]->maxe;
     60             if(e[v].b>_max) maxe=v;
     61         }
     62     } T[N<<1],E[N<<1],*null=&T[0];
     63     Node::Node(int x) {
     64         ch[0]=ch[1]=fa=null;
     65         rev=0; v=maxe=x;
     66     }
     67     
     68     void rot(Node* o,int d) {
     69         Node *p=o->fa;
     70         p->ch[d]=o->ch[d^1];
     71         o->ch[d^1]->fa=p;
     72         o->ch[d^1]=p;
     73         o->fa=p->fa;
     74         if(p==p->fa->ch[0])
     75             p->fa->ch[0]=o;
     76         else if(p==p->fa->ch[1])
     77             p->fa->ch[1]=o;
     78         p->fa=o;
     79         p->maintain();
     80     }
     81     void splay(Node* o) {
     82         o->up_push();
     83         Node* nf,*nff;
     84         while(o->fa->ch[0]==o||o->fa->ch[1]==o) {
     85             nf=o->fa,nff=nf->fa;
     86             if(o==nf->ch[0]) {
     87                 if(nf==nff->ch[0]) rot(nf,0);
     88                 rot(o,0);
     89             } else {
     90                 if(nf==nff->ch[1]) rot(nf,1);
     91                 rot(o,1);
     92             }
     93         }
     94         o->maintain();
     95     }
     96     void Access(Node *o) {
     97         Node *son=null;
     98         while(o!=null) {
     99             splay(o);
    100             o->ch[1]=son;
    101             o->maintain();
    102             son=o; o=o->fa;
    103         }
    104     }
    105     void evert(Node *o) {
    106         Access(o);
    107         splay(o);
    108         o->reverse();
    109     }
    110     void Link(Node *u,Node *v) {
    111         evert(u);
    112         u->fa=v;
    113     }
    114     void Cut(Node *u,Node *v) {
    115         evert(u);
    116         Access(v),splay(v);
    117         v->ch[0]=u->fa=null;
    118         v->maintain();
    119     }
    120     Node *find(Node *o) {
    121         while(o->fa!=null) o=o->fa;
    122         return o;
    123     }
    124     
    125 }
    126 using namespace LCT ;
    127 
    128 int n,m;
    129 
    130 int query(Node *u,Node* v)
    131 {
    132     evert(u);
    133     Access(v),splay(v);
    134     return v->maxe;
    135 }
    136 
    137 int main()
    138 {
    139 //    freopen("in.in","r",stdin);
    140 //    freopen("out.out","w",stdout);
    141     n=read(),m=read();
    142     int u,v,a,b;
    143     FOR(i,1,m) {
    144         u=read(),v=read(),a=read(),b=read();
    145         adde(u,v,a,b);
    146     }
    147     FOR(i,1,m) E[i]=Node(i);
    148     FOR(i,1,n) T[i]=Node(0);
    149     sort(e+1,e+m+1);
    150     int ans=1e9;
    151     FOR(i,1,m) {
    152         int u=e[i].u,v=e[i].v;
    153         if(find(&T[u])==find(&T[v])) {
    154             int maxe=query(&T[u],&T[v]);
    155             if(e[i].b>=e[maxe].b) continue;
    156             Cut(&E[maxe],&T[e[maxe].u]);
    157             Cut(&E[maxe],&T[e[maxe].v]);
    158         }
    159         Link(&T[u],&E[i]);
    160         Link(&T[v],&E[i]);
    161         if(find(&T[1])==find(&T[n])) {
    162             int maxe=query(&T[1],&T[n]);
    163             if(e[maxe].b+e[i].a<ans) ans=e[maxe].b+e[i].a; 
    164         }
    165     }
    166     if(ans==1e9) puts("-1");
    167     else printf("%d
    ",ans);
    168     return 0;
    169 }
  • 相关阅读:
    LeetCode113. 路径总和 II
    LeetCode257. 二叉树的所有路径
    LeetCode222. 完全二叉树的节点个数
    LeetCode404. 左叶子之和
    LeetCode110. 平衡二叉树
    LeetCode101. 对称二叉树
    LeetCode100. 相同的树
    llustrator CC2017下载AI2020
    vs code 代码格式化整理
    人生格言
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5326502.html
Copyright © 2011-2022 走看看