首页 > 代码库 > BZOJ 1131 POI2008 Sta 树形DP
BZOJ 1131 POI2008 Sta 树形DP
题目大意:给定一个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; }
BZOJ 1131 POI2008 Sta 树形DP
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。