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 
原文地址:https://www.cnblogs.com/hjj1871984569/p/5705877.html