1131: [POI2008]Sta
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1705 Solved: 640
[ 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
默认根为1
DFS求出每个点的子树大小,以及每个点的深度,设sum为树中所有节点的深度和
然后以每个点为根的树深度和可以从相邻点O(1)转移出来,再DFS一次就好
#include<stdio.h>
#include<vector>
using namespace std;
#define LL long long
vector<int> G[1000005];
int size[1000005], dep[1000005], n, ans;
LL sum, now;
int Read()
{
int x = 0, f = 1;
char ch;
ch = getchar();
while(ch<'0' || ch>'9')
{
if(ch=='-') f = -1;
ch = getchar();
}
while(ch>='0' && ch<='9')
x = x*10+ch-'0', ch = getchar();
return x*f;
}
void Sech(int u, int p, int deep)
{
int i, v;
size[u] = 1;
dep[u] = deep;
for(i=0;i<G[u].size();i++)
{
v = G[u][i];
if(v==p)
continue;
Sech(v, u, deep+1);
size[u] += size[v];
}
}
void DP(int u, int p)
{
int i, v;
if(sum>now || sum==now && u<ans)
now = sum, ans = u;
for(i=0;i<G[u].size();i++)
{
v = G[u][i];
if(v==p)
continue;
sum += n-2*size[v];
DP(v, u);
sum -= n-2*size[v];
}
}
int main(void)
{
int i, x, y;
scanf("%d", &n);
for(i=1;i<=n-1;i++)
{
x = Read(), y = Read();
G[x].push_back(y);
G[y].push_back(x);
}
Sech(1, 0, 0);
for(i=1;i<=n;i++)
sum += dep[i];
DP(1, 0);
printf("%d\n", ans);
return 0;
}