树的重心,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 }
时间: 2024-10-12 00:04:53