浅谈树的重心

浅谈树的直径


定义:

  树上一节点最大子树的节点数最小;

性质:

  1.删除重心后所得的所有子树,节点数不超过原树的1/2,一棵树最多有两个重心;

  2.树中所有节点到重心的距离之和最小,如果有两个重心,那么他们距离之和相等;

  3.两个树通过一条边合并,新的重心在原树两个重心的路径上;

  4.树删除或添加一个叶子节点,重心最多只移动一条边;

求解:

  求解方法多种多样,分别用到不同的定义和性质:

  1.定义求解:

  siz [ i ]表示 i 节点的子树大小 dp [ i ]表示以 i 为根节点的最大子树大小,val[ i ]为i节点的点权,代码通俗易懂不过多解释了

  

inline void dfs(int now,int fa)
{
    siz[now]=val[now];
    dp[now]=0;
    for(int i=head[now];i;i=a[i].nxt)
    {
        int t=a[i].to;
        if(t==fa) continue;
        dfs(t,now);
        siz[now]+=siz[t];
        dp[now]=max(dp[now],siz[t]);
    }
    dp[now]=max(dp[now],n-dp[now]);
    if(dp[now]<dp[ans]) ans=now;
}

  2.性质求解:

  一般来说定义求解就够用了,但在某些时候性质求解更方便实用;

  根据性质2:我们可以处理出所有节点到某一节点的距离,取最小值;

  怎么求出每个节点到某一节点的距离呢?在dfs过程中向下处理是很容易的,所以我们可以先处理出所有节点到根节点的距离qwq ;

  siz [ i ]同上,f [ i ] 表示节点 i 的所有子节点到 i 的距离和,val[ i ] 同上, a [ i ].val 为边权,设定1 号节点为根节点;

  

inline void dfs1(int now,int fa,int deep)
{
    siz[now]=val[now];
    dep[now]=deep;
    for(int i=head[now];i;i=a[i].nxt)
    {
        int t=a[i].to;
        if(t==fa) continue;
        dfs1(t,now,deep+a[i].val);
        siz[now]+=siz[t];
        f[now]+=f[t]+siz[t]*a[i].val;
    }
}

  对于f数组的处理的理解:t的所有子节点到t的距离+now的当前子树所有节点到now的距离。

  这样就求得了根节点的距离和,我们再通过根节点递推其他节点的距离和,有如下公示:

  f [ now ] = f [ fa ] +( siz [ 根节点 ] - 2 * siz [ now ])* 边权;(now!= 根节点)

  理解如下:

  对于now的子节点,每个节点的距离减少了一个边权,总距离减少 siz [ now ] * 边权 ,对于非v子节点,每个节点距离增加了一个边权,总距离增加(siz[ 根 ]-siz [ now ])*边权

  

inline void dfs2(int now,int fa)
{
    if(now^root) f[now]=f[fa]+siz[1]-2*siz[now];
    if(f[now]<sum) res=now,sum=f[now];
    for(int i=head[now];i;i=a[i].nxt)
    {
        int t=a[i].to;
        if(t==fa) continue;
        dfs2(t,now);
    }
}

to be continue……

原文地址:https://www.cnblogs.com/knife-rose/p/11258403.html

时间: 2024-08-01 11:04:04

浅谈树的重心的相关文章

浅谈树状数组

还是区间求和区间修改的问题,我们使用线段树解决以后发现编程复杂度比较大 在这里介绍一个简单的数据结构,树状数组. 树状数组的优势是编程复杂度小,常数小,时间复杂度也不错 树状数组的查询,修改,都是LOG(N)级别的 下面来分析一下上面那个图看能得出什么规律: 据图可知:c1=a1,c2=a1+a2,c3=a3,c4=a1+a2+a3+a4,c5=a5,c6=a5+a6,c7=a7,c8=a1+a2+a3+a4+a5+a6+a7+a8,c9=a9,c10=a9+a10,c11=a11.......

浅谈树链剖分(C++、算法、树结构)

关于数链剖分我在网上看到的有几个比较好的讲解,本篇主要是对AC代码的注释(感谢各位witer的提供) 这是讲解 http://www.cnblogs.com/kuangbin/archive/2013/08/15/3259083.html 另一个是百度文库 http://wenku.baidu.com/link?url=DY8CAbwdjitIiv8XQsHmVPi--dQAqw5z6dc_6N1Plh4u5Nfc1aCADQm4oAvt4Sqe1mXSixezzK4lRxofQKMX9cNzJ

浅谈树链剖分

今天刚学会树剖......(是不是觉得我很菜QwQ) 树剖的用处: 引子问题1: 给你一颗树,支持两种操作: 1.给x到y路径上的值加z 2.求出点x的值 简单,树上差分嘛,前几天刚学过啊. 引子问题2: 给你一颗树,支持两种操作: 1.给以x为根的子树加z 2.求出以x为根的子树的和. 简单,dfs序+线段树啊. 那么把两个问题结合起来呢?——树链剖分华丽丽登场!!! 树剖核心思想: 听说线段树挺好用的,区改区查只要log的复杂度,但是只能在线性结构上用,哎,真是太遗憾了. 听说有一种叫做df

蒟蒻浅谈树链剖分之一——两个dfs操作

树链剖分,顾名思义就是将树形的结构剖分成链,我们以此便于在链上操作 首先我们需要明白在树链剖分中的一些概念 重儿子:某节点所有儿子中子树最多的儿子 重链:有重儿子构成的链 dfs序:按重儿子优先遍历时的顺序 轻儿子的意思就与重儿子相反 首先是第一个dfs操作 在本次操作中,我们主要做的是处理所有节点的父亲,子树大小,重儿子,深度等操作 void dfs1(int now,int father,int deep) { tree[now].depth=deep;//初始化当前节点的深度,子树大小,父

浅谈树状数组套主席树

话说主席树还没写就先写这一篇了\(qwq\) 回顾一下主席树的实现过程:类似查分思想,将线段树的每次修改看做函数式以支持可持久化.因为这样的线段树是可减的. 那么我们维护信息的时候,就要维护每一次新形成的信息.但是我们可以根据前一个信息的基础上进行改动,而不必要去再建一棵树. 所以总而言之,是前缀和的思想. 那么,当需要修改的时候,怎么做呢? 考虑普通的区间操作,当做单点修改的时候,一般用树状数组,线段树和分块.最好实现的就是树状数组. 考虑用树状数组来维护主席树的信息. 树状数组中维护了每一次

浅谈二维中的树状数组与线段树

一般来说,树状数组可以实现的东西线段树均可胜任,实际应用中也是如此.但是在二维中,线段树的操作变得太过复杂,更新子矩阵时第一维的lazy标记更是麻烦到不行. 但是树状数组在某些询问中又无法胜任,如最值等不符合区间减法的询问.此时就需要根据线段树与树状数组的优缺点来选择了. 做一下基本操作的对比,如下图. 因为线段树为自上向下更新,从而可以使用lazy标记使得矩阵的更新变的高校起来,几个不足就是代码长,代码长和代码长. 对于将将矩阵内元素变为某个值,因为树状数组自下向上更新,且要满足区间加法等限制

浅谈算法和数据结构: 九 平衡查找树之红黑树

原文:浅谈算法和数据结构: 九 平衡查找树之红黑树 前面一篇文章介绍了2-3查找树,可以看到,2-3查找树能保证在插入元素之后能保持树的平衡状态,最坏情况下即所有的子节点都是2-node,树的高度为lgN,从而保证了最坏情况下的时间复杂度.但是2-3树实现起来比较复杂,本文介绍一种简单实现2-3树的数据结构,即红黑树(Red-Black Tree) 定义 红黑树的主要是像是对2-3查找树进行编码,尤其是对2-3查找树中的3-nodes节点添加额外的信息.红黑树中将节点之间的链接分为两种不同类型,

浅谈算法和数据结构: 十 平衡查找树之B树

转载自 http://www.cnblogs.com/yangecnu/p/3632027.html 浅谈算法和数据结构: 十 平衡查找树之B树 前面讲解了平衡查找树中的2-3树以及其实现红黑树.2-3树种,一个节点最多有2个key,而红黑树则使用染色的方式来标识这两个key. 维基百科对B树的定义为“在计算机科学中,B树(B-tree)是一种树状数据结构,它能够存储数据.对其进行排序并允许以O(log n)的时间复杂度运行进行查找.顺序读取.插入和删除的数据结构.B树,概括来说是一个节点可以拥

浅谈 trie树 及其实现

定义:又称字典树,单词查找树或者前缀树,是一种用于快速检索的多叉树结构, 如英文字母的字典树是一个26叉树,数字的字典树是一个10叉树. 核心思想:是空间换时间.利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的. 三个基本性质: 1. 根结点不包含字符,除根结点外每一个结点都只包含一个字符. 2. 从根结点到某一结点,路径上经过的字符连接起来,为该结点对应的字符串. 3. 每个结点的所有子结点包含的字符都不相同. 优点:利用字符串的公共前缀来节约存储空间,最大限度地减少无谓的字符串比