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 }