• bzoj 3669 lct维护最小生成树


    大概题意:给一个无向图,有a,b两种边权,找一条从1到n的路径,使得max(a[i])+max(b[i])最小a[i],b[i]表示该路径上的边的对应权。

    如果用类似最短路的DP来做,显然每个点的状态就必须是一个集合,保存的是一个下凸的点集,表示到达这个点的最小的a,b,这样肯定会挂,但该该种做法已经无法再优化或减少状态了。

    考虑枚举其中一个权值b0,然后只考虑所有b权值小于等于b0的边,然后变成简单的问题,因为这个b0不满足二分三分之类的性质,所以肯定不能每次重建图,跑DP,最终的做法是从小到大枚举一维权值,然后不断地加边进入边,维护一个当前图的最小生成树(用LCT实现)。

    收获:

      1、如果一个东西不满足二分三分,可以尝试从动态的角度,暴力枚举,用数据结构保证复杂度。

      1 /**************************************************************
      2     Problem: 3669
      3     User: idy002
      4     Language: C++
      5     Result: Accepted
      6     Time:6680 ms
      7     Memory:12536 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #include <algorithm>
     12 #define oo 0x3f3f3f3f
     13 #define N 200010
     14 using namespace std;
     15  
     16 struct Edge {
     17     int u, v, a, b;
     18     Edge(){}
     19     Edge( int u, int v, int a, int b ):u(u),v(v),a(a),b(b){}
     20     bool operator<( const Edge &e ) const { return b<e.b; }
     21 };
     22 struct LCT {
     23     int son[N][2], pre[N], pnt[N], rtg[N], ntot;
     24     int trash[N], stot;
     25     int val[N], vmx[N], vnd[N], uu[N], vv[N];
     26  
     27     inline int newnode( int p, int va, int u, int v ) {
     28         int nd = stot ? trash[stot--] : ++ntot;
     29         pre[nd] = p;
     30         son[nd][0] = son[nd][1] = pnt[nd] = 0;
     31         rtg[nd] = 0;
     32         val[nd] = vmx[nd] = va;
     33         vnd[nd] = nd;
     34         uu[nd] = u;
     35         vv[nd] = v;
     36         return nd;
     37     }
     38     void update( int nd ) {
     39         vmx[nd] = val[nd];
     40         vmx[nd] = max( vmx[nd], vmx[son[nd][0]] );
     41         vmx[nd] = max( vmx[nd], vmx[son[nd][1]] );
     42         if( vmx[nd]==val[nd] )
     43             vnd[nd] = nd;
     44         else if( vmx[nd]==vmx[son[nd][0]] )
     45             vnd[nd] = vnd[son[nd][0]];
     46         else
     47             vnd[nd] = vnd[son[nd][1]];
     48     }
     49     void rotate( int nd, int d ) {
     50         int p = pre[nd];
     51         int s = son[nd][!d];
     52         int ss = son[s][d];
     53  
     54         son[nd][!d] = ss;
     55         son[s][d] = nd;
     56         if( p ) son[p][ nd==son[p][1] ] = s;
     57         else pnt[s]=pnt[nd], pnt[nd]=0;
     58  
     59         pre[nd] = s;
     60         pre[s] = p;
     61         if( ss ) pre[ss] = nd;
     62  
     63         update(nd);
     64         update(s);
     65     }
     66     void bigp( int nd ) {
     67         if( pre[nd] ) bigp(pre[nd]);
     68         if( rtg[nd] ) {
     69             rtg[son[nd][0]] ^= 1;
     70             rtg[son[nd][1]] ^= 1;
     71             swap( son[nd][0], son[nd][1] );
     72             rtg[nd] = 0;
     73         }
     74     }
     75     void splay( int nd, int top=0 ) {
     76         bigp(nd);
     77         while( pre[nd]!=top ) {
     78             int p=pre[nd];
     79             int nl=nd==son[p][0];
     80             if( pre[p]==top ) {
     81                 rotate( p, nl );
     82             } else {
     83                 int pp=pre[p];
     84                 int pl=p==son[pp][0];
     85                 if( nl==pl ) {
     86                     rotate( pp, pl );
     87                     rotate( p, nl );
     88                 } else {
     89                     rotate( p, nl );
     90                     rotate( pp, pl );
     91                 }
     92             }
     93         }
     94     }
     95     void access( int nd ) {
     96         int u = nd;
     97         int v = 0;
     98         while( u ) {
     99             splay( u );
    100             int s=son[u][1];
    101             if( s ) {
    102                 pre[s] = 0;
    103                 pnt[s] = u;
    104             } 
    105             son[u][1] = 0;
    106             if( v ) {
    107                 pre[v] = u;
    108                 pnt[v] = 0;
    109             }
    110             son[u][1] = v;
    111             update(u);
    112             v = u;
    113             u = pnt[u];
    114         }
    115         splay( nd );
    116     }
    117     void makeroot( int u ) {
    118         access(u);
    119         rtg[u] ^= 1;
    120     }
    121     void init( int n ) {
    122         ntot = n;
    123         val[0] = -1;
    124     }
    125     int findroot( int u ) {
    126         while( pre[u] ) u=pre[u];
    127         while( pnt[u] ) {
    128             u=pnt[u];
    129             while( pre[u] ) u=pre[u];
    130         }
    131         return u;
    132     }
    133     bool sameroot( int u, int v ) {
    134         return findroot(u)==findroot(v);
    135     }
    136     int query( int s, int t ) {
    137         makeroot(s);
    138         access(t);
    139         return vmx[t];
    140     }
    141     void addedge( int u, int v, int w ) {
    142 //      fprintf( stderr, "addedge( %d %d %d )
    ", u, v, w );
    143         if( sameroot(u,v) ) {
    144             if( query(u,v)<=w ) return;
    145             makeroot(u);
    146             access(v);
    147             int nd = vnd[v];
    148             int l = uu[nd];
    149             int r = vv[nd];
    150             makeroot(l);
    151             access(r);
    152             bigp(l);
    153             int e = son[r][0];
    154             while( son[e][1] ) e=son[e][1];
    155             splay(e);
    156             pre[l] = pre[r] = 0;
    157             trash[++stot] = e;
    158         } 
    159         makeroot(u);
    160         makeroot(v);
    161         int nd = newnode(0,w,u,v);
    162         pnt[u] = nd;
    163         pnt[v] = nd;
    164     }
    165     void print() {
    166         fprintf( stderr, "
    " );
    167         for( int i=1; i<=ntot; i++ ) {
    168             int nd = i;
    169             for( int j=1; j<=stot; j++ )
    170                 if( i==trash[j] ) 
    171                     goto Next;
    172             fprintf( stderr, "%d pnt=%d pre=%d ls=%d rs=%d rtg=%d val=%d vmx=%d vnd=%d uu=%d vv=%d
    ",
    173                     nd, pnt[nd], pre[nd], son[nd][0], son[nd][1], rtg[nd], val[nd], vmx[nd], vnd[nd], uu[nd], vv[nd] );
    174 Next:;
    175         }
    176     }
    177 }T;
    178  
    179 int n, m;
    180 Edge edge[N];
    181  
    182 int main() {
    183     scanf( "%d%d", &n, &m );
    184     for( int i=1,u,v,a,b; i<=m; i++ ) {
    185         scanf( "%d%d%d%d", &u, &v, &a, &b );
    186         edge[i] = Edge(u,v,a,b);
    187     }
    188     sort( edge+1, edge+1+m );
    189     T.init(n);
    190     int ans = oo;
    191     for( int i=1,j; i<=m; i=j ) {
    192         for( j=i; j<=m; j++ ) {
    193             if( edge[j].b==edge[i].b ) 
    194                 T.addedge(edge[j].u,edge[j].v,edge[j].a);
    195             else break;
    196         }
    197         if( !T.sameroot(1,n) ) continue;
    198         ans = min( ans, edge[i].b+T.query(1,n) );
    199     }
    200     printf( "%d
    ", ans==oo ? -1 : ans );
    201 }
    View Code
  • 相关阅读:
    filterFilter用法
    angular.copy()克隆数据
    angularjs中是否选择所有和$filter过滤orderBy排序
    qt5.5 qtcreator中文乱码
    shared_ptr
    Thrift-0.9.2编译安装
    一行代码获取通讯录联系框架
    IOS枚举使用
    Static Cell-静态TableView
    NavigationController的使用整理
  • 原文地址:https://www.cnblogs.com/idy002/p/4502101.html
Copyright © 2020-2023  润新知