POJ 3107

树的重心,EASY题。

树的重心定义为:找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重

心后,生成的多棵树尽可能平衡.  实际上树的重心在树的点分治中有重要的作用, 可以避免N^2的极端复杂度(从退化链的一端出发),保证

NlogN的复杂度, 利用树型dp可以很好地求树的重心.

 

 1 #include <cstdio> 
 2 #include <iostream> 
 3 #include <cstring>  
 4 #include <cctype>  
 5 #include <algorithm>  
 6 #define LL unsigned __int64
 7 using namespace std; 
 8 
 9 const int N=  50100;
10 
11 struct Edge{
12     int u,v;
13     int next;
14 }edge[N*2];
15 int head[N],tot,maxt;
16 int dp[N],n,ans[N],anc;
17 
18 void addedge(int u,int v){
19     edge[tot].u=u;
20     edge[tot].v=v;
21     edge[tot].next=head[u];
22     head[u]=tot++;
23 }
24 
25 void dfs(int u,int f){
26     dp[u]=1;
27     int tmp=-1;
28     int v;
29     for(int e=head[u];e!=-1;e=edge[e].next){
30         v=edge[e].v;
31         if(v!=f){
32             dfs(v,u);
33             dp[u]+=dp[v];
34             tmp=max(tmp,dp[v]);
35         }
36     }
37     tmp=max(tmp,n-dp[u]);
38     if(tmp<maxt){
39         anc=0;
40         maxt=tmp;
41         ans[anc++]=u;
42     }
43     else if(tmp==maxt)
44     ans[anc++]=u;
45 }
46 
47 int main(){
48     int u,v;
49     while(scanf("%d",&n)!=EOF){
50         for(int i=1;i<=n;i++){
51             head[i]=-1; dp[i]=0;
52         }
53         tot=0; anc=0; maxt=N*10;
54         for(int i=1;i<n;i++){
55             scanf("%d%d",&u,&v);
56             addedge(u,v);
57             addedge(v,u);
58         }
59         dfs(1,-1);
60         sort(ans,ans+anc);
61         printf("%d",ans[0]);
62         for(int i=1;i<anc;i++)
63         printf(" %d",ans[i]);
64         puts("");
65     }
66     return 0;
67 }
View Code

 

转载于:https://www.cnblogs.com/jie-dcai/p/4330986.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值