• 树上问题——树的直径


    树的直径的含义

    树的直径就是树中所有最短路经距离的最大值。

    求树的直径通常有两种方法,一种是通过两次搜索(bfs和dfs均可),另一种就是通过树形dp来求了。

    dfs(bfs)求树的直径

    随便从一个点 a a a开始,用dfs找到离初始点最远的点 b b b。然后再以最远点 b b b为初始点用dfs找到离初始点最远的点 c c c

    路径 b c bc bc即为当前树的直径。

    int e,maxv=-1;
    void dfs(int x,int father)
    {
    	for(int i=h[x];i!=-1;i=ne[i])//用链式前向星存树
    	{
    		int j=e[i];
    		if(j==father) continue;//树是一种有向无环图,只要搜索过程中不返回父亲节点即可保证不会重复遍历同一个点。
    		d[j]=d[x]+w[i];//更新每个点到起始点的距离(在树中任意两点的距离是唯一的)
            if(d[j]>maxv) maxv=d[j],e=j;//更新最远的点的信息
    		dfs(j,x);//继续搜索下一个节点
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    树形dp求树的直径

    首先递归到叶结点,然后再由叶结点连接父节点,更新 f 1 , f 2 f1,f2 f1,f2数组( f 1 [ i ] f1[i] f1[i]数组表示离点i最远的点的距离, f 2 [ i ] f2[i] f2[i]数组表示离点i次远的点的距离)。

    最后找到任意一点的 f 1 + f 2 f1+f2 f1+f2最大的值,该值即为树的直径。

    void dp(int x,int father)
    {
    	for(int i=h[x];i!=-1;i=ne[i])链式前向星存树
    	{
    		int j=e[i];
    		if(j==father) continue;//防止原路返回
    		dp(j,x);//dp过程应该是由叶节点开始的,也就是说先递归到叶节点再开始进行状态转移
    		if(f1[x]
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  • 相关阅读:
    PaddleSeg 自定义数据类
    Zookeeper原生API和Curator两种方式实现ZK分布式锁
    全网最详细SpringBoot、SpringCloud整合阿里云短信服务
    现代c++手撸2309神经网络最简化版230901
    Harmony Next 文件命令操作(发送、读取、媒体文件查询)
    密钥密码学(三)
    嵌入式系统日志轮转:实现与性能考量
    Java面试整理(三)《JavaSE》
    Dubbo 与 Spring Cloud 完美结合
    hcie培训价格多少钱?
  • 原文地址:https://blog.csdn.net/qq_57109165/article/details/126708979