bzoj 1776
收获:
树上直径一定包含深度最深的点。
然后O(nlogn) 暴力。
1 /************************************************************** 2 Problem: 1776 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:2064 ms 7 Memory:31756 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <vector> 12 #define maxn 200010 13 #define maxp 18 14 using namespace std; 15 16 int n, m, root; 17 int anc[maxn][maxp+1], dep[maxn]; 18 vector<int> g[maxn]; 19 vector<int> grp[maxn]; 20 21 void dfs( int u ) { 22 for( int p=1; p<=maxp; p++ ) 23 anc[u][p]=anc[anc[u][p-1]][p-1]; 24 for( int t=0; t<g[u].size(); t++ ) { 25 int v=g[u][t]; 26 anc[v][0] = u; 27 dep[v] = dep[u]+1; 28 dfs( v ); 29 } 30 } 31 int lca( int u, int v ) { 32 if( dep[u]<dep[v] ) swap(u,v); 33 int t=dep[u]-dep[v]; 34 for( int p=0; t; t>>=1,p++ ) 35 if( t&1 ) u=anc[u][p]; 36 if( u==v ) return u; 37 for( int p=maxp; anc[u][0]!=anc[v][0]; p-- ) 38 if( anc[u][p]!=anc[v][p] ) 39 u=anc[u][p],v=anc[v][p]; 40 return anc[u][0]; 41 } 42 int main() { 43 scanf( "%d%d", &n, &m ); 44 for( int i=1,a,b; i<=n; i++ ) { 45 scanf( "%d%d", &a, &b ); 46 grp[a].push_back( i ); 47 if( b==0 ) root=i; 48 else g[b].push_back( i ); 49 } 50 dep[root] = 0; 51 anc[root][0] = root; 52 dfs(root); 53 for( int i=1; i<=m; i++ ) { 54 int md = grp[i][0]; 55 for( int t=1; t<grp[i].size(); t++ ) 56 if( dep[grp[i][t]]>dep[md] ) 57 md=grp[i][t]; 58 int u=md; 59 int ans=0; 60 for( int t=0; t<grp[i].size(); t++ ) { 61 int v=grp[i][t]; 62 int ca=lca(u,v); 63 int dis = dep[u]+dep[v]-dep[ca]-dep[ca]; 64 if( ans<dis ) ans=dis; 65 } 66 printf( "%d\n", ans ); 67 } 68 }