BZOJ 1131: [POI2008]Sta

1131: [POI2008]Sta

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1370  Solved: 486
[Submit][Status][Discuss]

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

HINT

 

Source

 
[Submit][Status][Discuss]

 

分析

一开始不妨拿1当作根节点,预处理出每个子树的结点个数,然后从1开始DFS,在相邻点种枚举新的根,可以O(1)的得到新的SON数组以及深度之和。

 

代码

 1 #include <cmath>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <iostream>
 6 #include <algorithm>
 7  
 8 using namespace std;
 9  
10 const int N = 5000005;
11  
12 int n, id = 1;
13  
14 long long sum, ans, son[N];
15  
16 int hd[N], nt[N], to[N], tot;
17  
18 void add(int x, int y)
19 {
20     nt[tot] = hd[x]; to[tot] = y; hd[x] = tot++;
21     nt[tot] = hd[y]; to[tot] = x; hd[y] = tot++;
22 }
23  
24 void prework(int u, int f, int d)
25 {
26     sum += d; son[u] = 1;
27      
28     for (int i = hd[u]; ~i; i = nt[i])
29         if (to[i] != f)prework(to[i], u, d + 1), son[u] += son[to[i]];
30 }
31  
32 void search(int u, int f, long long s)
33 {
34     if (ans < s || (ans == s && id > u))
35         ans = s, id = u;
36      
37     for (int i = hd[u]; ~i; i = nt[i])
38         if (to[i] != f)search(to[i], u, s + n - son[to[i]]*2);
39 }
40  
41 signed main(void)
42 {
43     scanf("%d", &n); 
44      
45     memset(hd, -1, sizeof(hd)); tot =0; 
46      
47     for (int i = 1, x, y; i < n; ++i)
48         scanf("%d%d", &x, &y), add(x, y);
49          
50     prework(1, -1, 0); search(1, -1, sum);
51      
52     printf("%d\n", id);
53 }
BZOJ_1131.cpp

 

@Author: YouSiki

posted @ 2016-11-22 22:53  YouSiki  阅读(251)  评论(0编辑  收藏  举报