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
", ans );
67     }
68 }
View Code
原文地址:https://www.cnblogs.com/idy002/p/4344195.html