bzoj 1131: [POI2008]Sta(树形DP)

1131: [POI2008]Sta

Time Limit: 10 Sec   Memory Limit: 162 MB
Submit: 1140   Solved: 373
[ 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当作根求出总和,然后转移即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define  N 2000003
using namespace std;
int n,m;
int point[N],next[N],v[N],deep[N],tot,size[N];
long long f[N],ans;
int ansx;
void add(int x,int y)
{
	tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y;
	tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x;  
}
void dfs(int x,int fa)
{
	size[x]=1;
	for (int i=point[x];i;i=next[i])
	 if (v[i]!=fa)
	  {
	  	dfs(v[i],x);
	  	deep[v[i]]=deep[x]+1;
	  	size[x]+=size[v[i]];
	  }
}
void dp(int x,int fa)
{
	for (int i=point[x];i;i=next[i])
	 if (v[i]!=fa)
	  {
	  	f[v[i]]=(long long)f[x]-(long long)size[v[i]]+(long long)n-size[v[i]];
	  	if (ans<f[v[i]])
	  	 ans=f[v[i]],ansx=v[i];
	  	if (ans==f[v[i]]&&ansx>v[i])
	  	 ansx=v[i];
	  	dp(v[i],x);
	  }
}
int main()
{
	scanf("%d",&n);
	for (int i=1;i<n;i++)
	 {
	 	int x,y; scanf("%d%d",&x,&y);
	 	add(x,y);
	 }
	deep[1]=1;
	dfs(1,0);
	for (int i=1;i<=n;i++)
	 f[1]+=(long long)deep[i];
	ans=f[1],ansx=1;
	dp(1,0);
	printf("%d\n",ansx);
}



你可能感兴趣的:(bzoj 1131: [POI2008]Sta(树形DP))