树的重心入门

  • 树的重心对于一棵\(n\)个结点的无根树,找到一个点,使得把树变成以该点为根的有根树树时,最大子树的结点数最小。 删去重心后,生成的多棵树尽可能平衡。
  • 性质:
    • 性质 1 :树中所有点到某个点的距离和中,到重心的距离和是最小的,如果有两个重心,他们的距离和一样。
    • 性质 2 :把两棵树通过某一点相连得到一颗新的树,新的树的重心必然在连接原来两棵树重心的路径上。
    • 性质 3 :一棵树添加或者删除一个节点,树的重心最多只移动一条边的位置。
    • 性质 4:一棵树最多有两个重心,且相邻。
  • 模板详解核心\(dfs\)代码
  •  1 ll minl=inf,ans;
     2 /*
     3 sz数组表示以当前节点为根,向下的子树的节点数目
     4 dp数组表示以当前节点为根,子树中最大节点数目是多少
     5 */
     6 
     7 void dfs(int u,int fa){
     8     sz[u]=1;
     9     for(int i=head[u];~i;i=edge[i].nxt){
    10         int v=edge[i].to;
    11         if( v!=fa ){//无向图,不加这个会成环
    12             dfs(v,u);
    13             sz[u]+=sz[v];//回溯加一下
    14             dp[u]=max(dp[u],sz[v]);//每次遍历完一棵子树都比较
    15         }
    16     }
    17     
    18     dp[u]=max(dp[u],n-sz[u]);//不要忽略向上的节点个数,比较完之后便是当前节点的最大子树节点
    19     if( minl>dp[u]){
    20         minl=dp[u];
    21         ans=u;
    22     }
    23 }

     

  • 入门例题:here
    • 题意:求删除这个点后最大子树的节点数,以及这个点的编号,如果有多个点满足,求编号最小的点。
    • AC_Code:
    •  1 #include <iostream>
       2 #include <string.h>
       3 #include <stdio.h>
       4 
       5 using namespace std;
       6 const int maxn = 20005;
       7 const int inf = 0x3f3f3f3f;
       8 
       9 int head[maxn];
      10 int sz[maxn];
      11 int cnt,n;
      12 int ans,siz;
      13 
      14 struct Edge{
      15     int to;
      16     int nxt;
      17 };
      18 
      19 Edge edge[2*maxn];
      20 
      21 void Init(){
      22     cnt=0;
      23     siz=inf;
      24     memset(head,-1,sizeof(head));
      25 }
      26 
      27 void add(int u,int v){
      28     edge[cnt].to = v;
      29     edge[cnt].nxt = head[u];
      30     head[u] = cnt++;
      31 }
      32 
      33 void dfs(int u,int fa)
      34 {
      35     sz[u]=1;
      36     int tmp=0;
      37     for(int i=head[u];~i;i=edge[i].nxt){
      38         int v=edge[i].to;
      39         if(v!=fa){
      40             dfs(v,u);
      41             sz[u]+=sz[v];
      42             tmp=max(tmp,sz[v]);
      43         }
      44     }
      45     tmp=max(tmp,n-sz[u]);
      46     if(tmp<siz || (tmp==siz && u<ans)){
      47         ans=u;
      48         siz=tmp;
      49     }
      50 }
      51 
      52 int main()
      53 {
      54     int t;
      55     scanf("%d",&t);
      56     while(t--){
      57         Init();
      58         scanf("%d",&n);
      59         for(int i=1;i<=n-1;i++){
      60             int u,v;
      61             scanf("%d%d",&u,&v);
      62             add(u,v);add(v,u);
      63         }
      64         dfs(1,0);
      65         printf("%d %d\n",ans,siz);
      66     }
      67     return 0;
      68 }

       

posted @ 2020-07-13 13:33  swsyya  阅读(183)  评论(0编辑  收藏  举报

回到顶部