zoukankan      html  css  js  c++  java
  • (图论)树的直径

    引言

    树作为一种特殊的图,具有很多良好的性质,树的直径便是其中之一。

    定义

    树的直径有许多相近的定义。但由于没有找到比较权威的定义,就用自己的语言大概表述一下吧。
    对于一棵带非负边权的树,定义两点间距离为两点间路径的边权之和,树的直径就是距离最远的两点之间的路径,同时也称该距离为树的直径。
    简而言之,树的直径就是树上最长的简单路径

    性质

    1. 直径两端点一定是两个叶子节点。

    2. 距离任意点最远的点一定是直径的一个端点。

    3. 对于两棵树,如果第一棵树直径两端点为(u,v),第二棵树直径两端点为(x,y),用一条边将两棵树连接,那么新树的直径一定是u,v,x,y中的两个点。

    性质证明

    1. 显然成立,证明从略。

    2. 情况一:点a在直径((u,v))上。若存在点b使得$ dis(a,b) gt dis (a,u) ext{并且} dis(a,b) gt dis (a,v)$ ,则有 (dis(b,v) ext{或} dis(b,u) gt dis(u,v)),即((u,v))不是该树的直径,矛盾。
      情况二:点a不在直径((u,v))上。若存在点b使得$ dis(a,b) gt dis (a,u) ext{并且} dis(a,b) gt dis (a,v)$ ,不妨取直径的其中一个端点(u)分析。
      分析图如下(灵魂画手上线):
      图3.2.1

      图片注:(u),(v) 为直径端点,(c)((a,b) ext{与}(a,u))交点,(d)((a,u) ext{与}(v,u))交点。

      由于(dis(a,b) gt dis (a,u)) ,可知 (dis(c,b) gt dis (c,u)),进而得到(dis(d,b) gt dis (d,u)),最终可知(dis(v,b) gt dis (v,u)),即((u,v))不是该树的直径,矛盾。

    3. 如果新树直径不是原来两棵树中一棵的直径,那么新直径一定经过两棵树的连接边,新直径在原来每棵树中的部分一定是距离连接点最远的点,即一定是原树直径的一个端点。

    求解算法

    共有两种时间复杂度为 (O(N)) 的算法,一种是dp,另一种是贪心算法。

    方法一:动态规划

    根据定义,我们只需要求出最大链长即可。
    首先将该树转化为有根树。设(f[i])为以节点(i)为根的子树的最大深度,有状态转移方程$$f[i] = max_{j in s(i)}f[j]+1 quad ext{where (s(i)) is the set of the son nodes of node i.}$$那么在该子树中经过节点(i)的最长链长度为 (f[i]) 与次大 (f[j]) (缺省值为0)之和。在整个遍历过程中记录最大链长即可。

    方法二:贪心算法

    根据树的直径性质2,我们只需要任取一点(s)开始DFS(或BFS)即可找到距离该点的最远点,即直径端点之一,记为(u)。同样的,从节点(u)开始我们便可以找到另一个端点(v),过程中记录距离即可得到树的直径。
    相较于方法一,方法二可以更方便地找到直径的端点,进而得到直径的具体路径。

    Code

    暂略

    我思故我在
  • 相关阅读:
    MarkDown学习
    做网站的或者博客的网站
    Calendar日历简单用法
    Cron表达式范例
    CSVFileUtil 读取写入CSV文件简单工具类
    直接读取ZIP包数据 线上、线下方法
    Spring @Async/@Transactional 失效的原因及解决方案
    多线程学习 读写锁
    多线程学习 公平锁和非公平锁
    多线程学习 ThreadLocal的使用。
  • 原文地址:https://www.cnblogs.com/pisceskkk/p/10423535.html
Copyright © 2011-2022 走看看