码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 3107

时间:2015-03-11 22:59:37      阅读:133      评论:0      收藏:0      [点我收藏+]

标签:

树的重心,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

 

POJ 3107

标签:

原文地址:http://www.cnblogs.com/jie-dcai/p/4330986.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!