zoukankan      html  css  js  c++  java
  • bzoj 3784

    第三道点分治。

    首先找到黄学长的题解,他叫我参考XXX的题解,但已经没有了,然后找到另一个博客的简略题解,没看懂,最后看了一个晚上黄学长代码,写出来然后,写暴力都拍了小数据,但居然超时,。。。。然后改了一下存图方式,还是T,读入优化,还是T,最后把BFS找重心改成DFS找重心后才过的(因为DFS只遍历一遍,但BFS要多遍历几遍)。

    ————————————————————以上是废话————————————————————————

    题目:给定一个边带权的无根树,求长度排名为前m的路径的长度。

    首先,肯定不能求出所有路径来排序,因为n很大。但我们要求前m大的路径,容易想到,我们先求出极大路径,求出最大,删掉它,然后再加上新产生的极大路径,但我们怎么定义“极大路径”呢,是长度不能再延伸的路径吗,可以发现这样选择,求新产生的极大路径会出现问题。

    那这道题是怎么做的呢?在点分治时,每一个重心会对应很多棵子树,先对当前重心代表的那一棵树进行一次DFS,幷保存每个点的DFS序,以及DFS序中每个位置对应点到当前重心的距离,并且我们为每个点保存一个DFS序的区间,该区间包含根和包含它的子树的左边的子树(不包含它所在的子树),这样元素(lf,rg,x)代表dfs序上第x个点与区间[lf,rg]上代表的点的路径,即它代表一些路径而不是一条。并且可以证明每一条路径属于且仅属于其中一个元素。

    每个元素代表的路径中存在最长的路径,以该路径的长度为关键字将元素放进堆中,每次找到后,将那个元素分成两个。。。。。。。

    。。。。。。。。。。

      1 /**************************************************************
      2     Problem: 3784
      3     User: idy002
      4     Language: C++
      5     Result: Accepted
      6     Time:6940 ms
      7     Memory:208820 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #include <cctype>
     12 #include <vector>
     13 #include <queue>
     14 #define max(a,b) ((a)>(b)?(a):(b))
     15 #define N 50010
     16 #define S 2000010
     17 using namespace std;
     18  
     19 void gn( int &a ) {
     20     char ch;
     21     ch = getchar();
     22     while( ch<'0'||ch>'9' ) ch=getchar();
     23     a = 0;
     24     while( '0'<=ch&&ch<='9' ) {
     25         a = a*10+ch-'0';
     26         ch = getchar();
     27     }
     28 }
     29  
     30 int n, m;
     31 int head[N], dest[N+N], wght[N+N], next[N+N], ntot;
     32 int vis[N], dis[N], siz[N], bac[N], fat[N], tot_siz, cur_root;
     33 int qdis[S], qlf[S], qrg[S], clf, crg, ind;
     34 int stm[S][20], bin[20], log[N];
     35 int qu[N], bg, ed;
     36  
     37 struct Paths {
     38     int lf, rg, mx, cur;
     39     Paths( int lf, int rg, int mx, int cur ):lf(lf),rg(rg),mx(mx),cur(cur) {}
     40     bool operator<( const Paths & b ) const {
     41         return qdis[mx]+qdis[cur] < qdis[b.mx]+qdis[b.cur];
     42     }
     43 };
     44 priority_queue<Paths> pq;
     45  
     46 void insert( int u, int v, int w ) {
     47     ntot++;
     48     next[ntot] = head[u];
     49     wght[ntot] = w;
     50     dest[ntot] = v;
     51     head[u] = ntot;
     52 }
     53 void dfs_dis( int u ) {
     54     ind++;
     55     qdis[ind] = dis[u];
     56     qlf[ind] = clf;
     57     qrg[ind] = crg;
     58     for( int t=head[u]; t; t=next[t] ) {
     59         int v=dest[t], w=wght[t];
     60         if( vis[v] || v==fat[u] ) continue;
     61         dis[v] = dis[u]+w;
     62         fat[v] = u;
     63         dfs_dis( v );
     64     }
     65 }
     66  
     67 void dfs_root( int u ) {
     68     siz[u] = 1;
     69     bac[u] = 0;
     70     for( int t=head[u]; t; t=next[t] ) {
     71         int v=dest[t];
     72         if( vis[v] || v==fat[u] ) continue;
     73         fat[v] = u;
     74         dfs_root( v );
     75         siz[u] += siz[v];
     76         if( siz[v]>bac[u] ) bac[u]=siz[v];
     77     }
     78     if( bac[u]<tot_siz-siz[u] ) bac[u] = tot_siz-siz[u];
     79     if( bac[cur_root]>bac[u] ) cur_root=u;
     80 }
     81 void build_vdcp( int rt ) {
     82     tot_siz = siz[rt];
     83     cur_root = 0;
     84     fat[rt] = rt;
     85     dfs_root( rt );
     86     rt = cur_root;
     87     /*   find the core of the block that not cross the vertex of visited   */
     88     /*
     89     qu[bg=ed=1] = rt;
     90     fat[rt] = rt;
     91     siz[rt] = bac[rt] = 0;
     92     while( ed>=bg ) {
     93         int u=qu[bg++];
     94         for( int t=head[u]; t; t=next[t] ) {
     95             int v=dest[t];
     96             if( vis[v] || v==fat[u] ) continue;
     97             qu[++ed] = v;
     98             fat[v] = u;
     99             siz[u] = bac[u] = 0;
    100         }
    101     }
    102     for( int i=ed; i>=1; i-- ) {
    103         int u=qu[i];
    104         int p=fat[u];
    105         siz[u]++;
    106         siz[p] += siz[u];
    107         if( bac[p]<siz[u] ) bac[p]=siz[u];
    108     }
    109     for( int i=ed; i>=1; i-- ) {
    110         int u=qu[i];
    111         if( bac[u]<siz[rt]-siz[u] ) bac[u]=siz[rt]-siz[u];
    112     }
    113     for( int i=ed; i>=1; i-- ) {
    114         int u=qu[i];
    115         if( bac[rt]>bac[u] ) rt=u;
    116     }
    117     */
    118     /*   get the info of cur core   */
    119     ind++;
    120     qdis[ind] = 0;
    121     qlf[ind] = qrg[ind] = 0;
    122     clf = crg = ind;
    123     vis[rt] = true;
    124     for( int t=head[rt]; t; t=next[t] ) {
    125         int u=dest[t], w=wght[t];
    126         if( vis[u] ) continue;
    127         fat[u] = rt;
    128         dis[u] = w;
    129         fat[u] = u;
    130         dfs_dis( u );
    131         crg = ind;
    132     }
    133     for( int t=head[rt]; t; t=next[t] ) {
    134         int u=dest[t];
    135         if( vis[u] ) continue;
    136         build_vdcp( u );
    137     }
    138 }
    139 void build_stable() {
    140     bin[0] = 1;
    141     for( int i=1; i<20; i++ ) bin[i]=bin[i-1]<<1;
    142     log[0] = -1;
    143     for( int i=1; i<=n; i++ ) log[i]=log[i>>1]+1;
    144     for( int i=1; i<=ind; i++ ) stm[i][0] = i;
    145     for( int p=1; p<=log[n]; p++ )
    146         for( int i=1; i<=ind-bin[p]+1; i++ ) {
    147             int a = stm[i][p-1];
    148             int b = stm[i+bin[p-1]][p-1];
    149             stm[i][p] = qdis[a]>qdis[b] ? a : b;
    150         }
    151 }
    152 int rmq( int lf, int rg ) {
    153     int len = rg-lf+1;
    154     int p = log[len];
    155     int a = stm[lf][p];
    156     int b = stm[rg-bin[p]+1][p];
    157     return qdis[a]>qdis[b] ? a : b;
    158 }
    159 int main() {
    160     gn(n), gn(m);
    161     for( int i=1,u,v,w; i<n; i++ ) {
    162         gn(u), gn(v), gn(w);
    163         insert( u, v, w );
    164         insert( v, u, w );
    165     }
    166     bac[0] = n, siz[1] = n;
    167     build_vdcp( 1 );
    168     build_stable();
    169     for( int i=1; i<=ind; i++ )
    170         if( qlf[i] ) pq.push( Paths(qlf[i],qrg[i],rmq(qlf[i],qrg[i]),i) );
    171     for( int i=1; i<=m; i++ ) {
    172         Paths pth = pq.top();
    173         pq.pop();
    174         printf( "%d
    ", qdis[pth.mx]+qdis[pth.cur] );
    175         if( pth.lf<=pth.mx-1 ) pq.push( Paths(pth.lf,pth.mx-1,rmq(pth.lf,pth.mx-1),pth.cur) );
    176         if( pth.rg>=pth.mx+1 ) pq.push( Paths(pth.mx+1,pth.rg,rmq(pth.mx+1,pth.rg),pth.cur) );
    177     }
    178 }
    View Code
  • 相关阅读:
    遮罩层代码
    get方法传递中文数据的时候如何进行转码
    Eclipse常用快捷键
    VS常用快捷键
    Java笔记10-Object包装类型字符串
    MySQL常用命令
    Oracle笔记3-高级查询
    Oracle笔记2-数据库设计
    Java笔记9-正则表达式
    Java笔记8-抽象接口
  • 原文地址:https://www.cnblogs.com/idy002/p/4371529.html
Copyright © 2011-2022 走看看