bzoj1131: [POI2008]Sta

来源:互联网 发布:tor browser mac 编辑:程序博客网 时间:2024/06/05 09:50

给出一个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

题意简单粗暴
适合本蒟蒻的一道大水题

我们考虑先dfs一遍求出所有节点以1(随便选)为根节点的的深度之和。
接着我们考虑根节点从一个点的父亲转移到这个点深度会发生什么变化?
显然以这个点为根的子树中所有的节点深度减一,其余节点深度加1
所以我们得到
f[i]=f[fa[i]]-siz[i]+(n-siz[i])
=>f[i]=f[fa[i]]+n-2*siz[i]
所以只要在第一次dfs时顺便求出以I为根节点的子树的的大小就好

include

include

include

include

include

include

include

include

include

include

using namespace std;
inline int read()
{
char ch=’*’;
int f=1;
while(!isdigit(ch=getchar())) if(ch==’-‘) f=-1;
int num=ch-‘0’;
while(isdigit(ch=getchar())) num=num*10+ch-‘0’;
return num*f;
}
typedef long long ll;
const int maxn = 1000005;
struct edge{
int next,to;
}e[maxn<<1];
int cnt,h[maxn],siz[maxn],fa[maxn],dep[maxn];
long long f[maxn],ans;
int id;
inline void add(int from,int to)
{
e[++cnt].next=h[from];
e[cnt].to=to;
h[from]=cnt;
}
int n,m;
void dfs(int x)
{
siz[x]=1;
for(register int i=h[x];i;i=e[i].next)
{
int v=e[i].to;
if(v==fa[x]) continue ;
dep[v]=dep[x]+1;
fa[v]=x;
dfs(v);
siz[x]+=siz[v];
f[x]+=f[v]+siz[v];
}
return ;
}
void dp(int x)
{
if(x!=1)
f[x]=f[fa[x]]+(long long)n-(long long)siz[x]-(long long)siz[x];
for(register int i=h[x];i;i=e[i].next)
if(e[i].to!=fa[x]) dp(e[i].to);
return ;
}

int main()
{
n=read();
int u,v;
for(register int i=1;i

原创粉丝点击