题解:洛谷 B4016 树的直径

【题目来源】

洛谷:B4016 树的直径 - 洛谷

【题目描述】

给定一棵 \(n\) 个结点的树,树没有边权。请求出树的直径是多少,即树上最长的不重复经过一个点的路径长度是多少。

【输入】

第一行输入一个正整数 \(n\),表示结点个数。

第二行开始,往下一共 \(n-1\) 行,每一行两个正整数 \((u,v)\),表示一条边。

【输出】

输出一行,表示树的直径是多少。

【输入样例】

5
1 2
2 4
4 5
2 3

【输出样例】

3

【解题思路】

image

【算法标签】

《洛谷 B4016 树的直径》 #深度优先搜索DFS# #树形DP# #树的直径# #O2优化#

【代码详解】

#include <bits/stdc++.h>
using namespace std;
const int N = 100005, M = N*2;
int n, u, v, deep[N], t, maxx;
int h[N], e[M], ne[M], idx;

// 添加无向边
void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

// 深度优先搜索
void dfs(int u, int fa)
{
    // 计算当前节点的深度
    if (fa)
    {
        deep[u] = deep[fa] + 1;
    }

    // 更新最深节点
    if (deep[u] > maxx)
    {
        maxx = deep[u];  // 更新最大深度
        t = u;           // 记录最深的节点
    }
    
    // 遍历所有邻接节点
    for (int i = h[u]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (j == fa) continue;  // 跳过父节点
        dfs(j, u);  // 递归搜索子节点
    }
}

int main()
{
    memset(h, -1, sizeof(h));  // 初始化邻接表
    cin >> n;  // 读入节点数
    
    // 读入边,构建无向图
    for (int i = 1; i < n; i++)
    {
        cin >> u >> v;
        add(u, v), add(v, u);
    }
    
    // 第一次DFS:从任意节点1开始,找到最远的节点t
    dfs(1, 0);
    
    // 重置深度数组和最大深度
    memset(deep, 0, sizeof(deep));
    maxx = 0;
    
    // 第二次DFS:从节点t开始,找到离t最远的节点
    dfs(t, 0);
    
    // 输出树的直径(最远两节点间的距离)
    cout << maxx << endl;
    return 0;
}

【运行结果】

5
1 2
2 4
4 5
2 3
3
posted @ 2026-03-14 22:06  团爸讲算法  阅读(1)  评论(0)    收藏  举报