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\n", 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

 

posted @ 2015-03-27 13:17  idy002  阅读(204)  评论(0编辑  收藏