Processing math: 100%
浏览器标题切换
浏览器标题切换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]+n2siz[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 @   henry_y  阅读(135)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示