题目大意:给定一个n个点的无根树,要求找到一个根节点,使深度之和最大
令f[x]为以x为根的子树的深度之和
首先我们找到任意一个节点进行深搜,统计出每棵子树的大小,以及所有点的深度之和
然后再以该节点为根深搜一遍,此时状态从父节点转移至子节点,转移方程如下:
当我们将根节点从4节点变为5节点时,橙色部分每个点的深度+1,绿色部分每个点的深度-1
故得到状态转移方程:
f[x]=f[fa[x]]+n-2*size[x]
最后扫一遍数组即可出解
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 1001001 using namespace std; typedef long long ll; struct abcd{ int to,next; }table[M<<1]; int head[M],tot; int n,ans,fa[M],siz[M]; ll f[M]; //根节点深度为0 void Add(int x,int y) { table[++tot].to=y; table[tot].next=head[x]; head[x]=tot; } void DFS1(int x) { int i; siz[x]=1; for(i=head[x];i;i=table[i].next) { if(table[i].to==fa[x]) continue; fa[table[i].to]=x; DFS1(table[i].to); siz[x]+=siz[table[i].to]; f[x]+=f[table[i].to]+siz[table[i].to]; } } void DFS2(int x) { int i; if(x!=1) f[x]=f[fa[x]]+n-siz[x]-siz[x]; for(i=head[x];i;i=table[i].next) { if(table[i].to==fa[x]) continue; DFS2(table[i].to); } } int main() { int i,x,y; cin>>n; for(i=1;i<n;i++) { scanf("%d%d",&x,&y); Add(x,y); Add(y,x); } DFS1(1); DFS2(1); for(i=1;i<=n;i++) if(f[i]>f[ans]) ans=i; cout<<ans<<endl; }
原文地址:http://blog.csdn.net/popoqqq/article/details/40039517