浏览器标题切换
浏览器标题切换end
把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

[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

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 ) ;
} 

 

posted @ 2018-10-03 10:14  henry_y  阅读(134)  评论(0编辑  收藏  举报