zoukankan      html  css  js  c++  java
  • 树的重心入门

    • 树的重心对于一棵(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
        ",ans,siz);
        66     }
        67     return 0;
        68 }
  • 相关阅读:
    Java精选笔记_EL表达式
    Java精选笔记_文件上传与下载
    Java精选笔记_Servlet事件监听器
    windows 下安装perl Tk 模块
    html 基础
    用grep 筛选fastq 序列
    php 统计fasta 序列长度和GC含量
    perl 截取 fastq文件
    Java_基础知识回顾
    Git_期末总结
  • 原文地址:https://www.cnblogs.com/wsy107316/p/13292641.html
Copyright © 2011-2022 走看看