BZOJ1131/POI2008 Sta
题目:Sta
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1131
题目简介:给出一个N个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大。
分析:
(1)先处理以1为根时树上所有点的深度之和,接着转换根节点。
(2)转换根节点时,考虑转换根节点的影响:一部分点的深度会减小,一部分点的深度会增加。
(3)令g[x]表示以x为根时树上所有点的深度之和,f[x]表示x的子树上的节点个数。对于当前根节点v和儿子节点u而言,将当前根节点v更换为子节点u带来的影响:u的子树上的所有节点的深度减少1,其余节点的深度增加1,即g[u]=g[v]-f[u]+n-f[u];
(4)这道题n的范围有点大,g数组要使用long long 类型,使用DFS可能会栈溢出。
(5)这道题n的范围有点大,添加读入优化速度有非常大的提高。
代码:
我比较懒,没打读入优化。
递归版:
1 #include <cstdio> 2 #define LL long long 3 LL max=0,ans=0,f0[1000005],f1[1000005],g1[1000005]; 4 int n,size,first[1000005]; 5 struct Edge{int to,next;}e[2000005]; 6 void addedge(int x,int y){ 7 e[++size].to=y;e[size].next=first[x];first[x]=size; 8 e[++size].to=x;e[size].next=first[y];first[y]=size; 9 } 10 void Tree_UP(int fa,int v){ 11 f0[v]=1; 12 for(int i=first[v],u;i;i=e[i].next){ 13 u=e[i].to;if(u==fa)continue; 14 Tree_UP(v,u); 15 f0[v]+=f0[u]; 16 f1[v]+=f1[u]+f0[u]; 17 } 18 } 19 void Tree_Down(int fa,int v){ 20 if(g1[v]>max || (g1[v]==max)&&(v<ans)){ 21 max=g1[v];ans=v; 22 } 23 for(int i=first[v],u;i;i=e[i].next){ 24 u=e[i].to;if(u==fa)continue; 25 g1[u]=g1[v]-f0[u]+n-f0[u]; 26 Tree_Down(v,u); 27 } 28 } 29 int main(){ 30 //freopen("in.txt","r",stdin); 31 //freopen("out.txt","w",stdout); 32 scanf("%d",&n); 33 for(int i=1,u,v;i<n;++i){ 34 scanf("%d %d",&u,&v); 35 addedge(u,v); 36 } 37 Tree_UP(-1,1); 38 g1[1]=f1[1]; 39 Tree_Down(-1,1); 40 printf("%lld",ans); 41 //fclose(stdin);fclose(stdout); 42 return 0; 43 }
非递归版:
1 #include <cstdio> 2 #define LL long long 3 LL max=0,f[1000005],g[1000005]; 4 int n,ans,size,first[1000005],q[1000005],fa[1000005]; 5 struct Edge{int to,next;}e[2000005]; 6 void addedge(int x,int y){ 7 e[++size].to=y;e[size].next=first[x];first[x]=size; 8 e[++size].to=x;e[size].next=first[y];first[y]=size; 9 } 10 void Tree_UP(){ 11 int h=1,t=1;q[1]=1; 12 for(int v;h<=t;++h){ 13 v=q[h]; 14 for(int i=first[v],u;i;i=e[i].next){ 15 u=e[i].to;if(u==fa[v])continue; 16 fa[u]=v;q[++t]=u; 17 } 18 } 19 for(int v;t;--t){ 20 v=q[t];f[v]=1; 21 for(int i=first[v],u;i;i=e[i].next){ 22 u=e[i].to;if(u==fa[v])continue; 23 f[v]+=f[u]; 24 } 25 g[1]+=f[v]; 26 } 27 } 28 void Tree_Down(){ 29 int h=1,t=1;q[1]=1; 30 for(int v;h<=t;++h){ 31 v=q[h]; 32 if(g[v]>g[ans] || (g[v]==g[ans])&&(v<ans))ans=v; 33 for(int i=first[v],u;i;i=e[i].next){ 34 u=e[i].to;if(u==fa[v])continue; 35 q[++t]=u; 36 g[u]=g[v]-f[u]+n-f[u]; 37 } 38 } 39 } 40 int main(){ 41 //freopen("in.txt","r",stdin); 42 //freopen("out.txt","w",stdout); 43 scanf("%d",&n); 44 for(int i=1,u,v;i<n;++i){ 45 scanf("%d %d",&u,&v); 46 addedge(u,v); 47 } 48 Tree_UP(); 49 Tree_Down(); 50 printf("%d",ans); 51 //fclose(stdin);fclose(stdout); 52 return 0; 53 } 54