[BZOJ1131][POI2008]Sta
Description
给出一个N个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大
Input
给出一个数字N,代表有N个点.N<=1000000 下面N-1条边.
Output
输出你所找到的点,如果具有多个解,请输出编号最小的那个.
Sample Input
8
1 4
5 6
4 5
6 7
6 8
2 4
3 4
1 4
5 6
4 5
6 7
6 8
2 4
3 4
Sample Output
7
Solution
做法:树形$dp$
事实上树形$dp$一遍之后以某个节点为根的情况就可以直接$O(1)$转移了,所以直接做就好了
设$f[i]$表示以$i$为根的情况
$f[ son ] = f[ u ] + n - 2 * siz[ son ] $
#include <bits/stdc++.h> using namespace std ; #define ll long long #define N 2000010 int ans = 0 , n ; int cnt , head[ N ] ; ll f[ N ] , siz[ N ] , dep[ N ] ; struct node { int to , nxt ; }e[ N ]; void ins( int u , int v ) { e[ ++ cnt ].to = v ; e[ cnt ].nxt = head[ u ] ; head[ u ] = cnt ; } void dfs1( int u , int fa ) { siz[ u ] = 1 ; f[ u ] = dep[ u ] ; for( int i = head[ u ] ; i ; i = e[ i ].nxt ) { if( e[ i ].to == fa ) continue ; dep[ e[ i ].to ] = dep[ u ] + 1 ; dfs1( e[ i ].to , u ) ; siz[ u ] += siz[ e[ i ].to ] ; f[ u ] += f[ e[ i ].to ] ; } } void dfs2( int u , int fa ) { for( int i = head[ u ] ; i ; i = e[ i ].nxt ) { if( e[ i ].to == fa ) continue ; f[ e[ i ].to ] = f[ u ] + n - 2 * siz[ e[ i ].to ] ; dfs2( e[ i ].to , u ) ; } } int main() { scanf( "%d" , &n ) ; for( int i = 1 ; i < n ; i ++ ) { int x , y ; scanf( "%d%d" , &x , &y ) ; ins( x , y ) ;ins( y , x ) ; } dfs1( 1 , 0 ) ; dfs2( 1 , 0 ) ; for( int i = 1 ; i <= n ; i ++ ) { if( f[ i ] > f[ ans ] ) ans = i ; } printf( "%d\n" , ans ) ; }