【图论】树的直径

树的直径即为一棵树中距离最远的两点之间的路径

方法一:DFS

先以任意一点为起点跑一遍dfs,记录离起点距离最远的点p(这个点一定是直径的一个端点,感性理解一下不证明了),然后再以最远点再跑一遍dfs,记录此时距离最远的点q,那么pq就是该树的直接

树中有负权边时不可以用这个方法

cpp 复制代码
const int N = 10000 + 10;

int n, c, d[N];
vector<int> g[N];

void dfs(int u, int fa)
{
    for (int v : E[u])
    {
        if (v == fa) continue;
        d[v] = d[u] + 1; // 如边有权值,把1换成权值即可
        if (d[v] > d[c]) c = v; // 更新最大距离的点
        dfs(v, u);
    }
}

int main()
{
    cin >> n;
    for (int i = 1; i < n; i++)
    {
        int u, v;
        scanf("%d %d", &u, &v);
        g[u].push_back(v), g[v].push_back(u);
    }
    dfs(1, 0); // 第一遍dfs
    int p = c; // 一个端点
    d[c] = 0;
    dfs(c, 0); // 第二遍dfs
    int q = c; // 另一个端点
    cout << d[c];
    return 0;
}

方法二:树形dp

dp[u]为以u为根的子树中离u最远的点的路径长度

转移方程(v为u的子结点):dp[u] = max(dp[u], dp[v] + w(u, v))

两条经过根结点的最长路径即为该子树中的直径

转移方程:zj = max(zj, dp[u] + dp[v] + w(u, v))

cpp 复制代码
const int N = 10000 + 10;

int n, zj = 0;
int dp[N];
vector<int> g[N];

void dfs(int u, int fa)
{
    for (int v : E[u])
    {
        if (v == fa) continue;
        dfs(v, u);
        zj = max(zj, dp[u] + dp[v] + 1); // 如为有权边,把1换成权值即可
        dp[u] = max(dp[u], dp[v] + 1); // 如为有权边,把1换成权值即可
    }
}

int main()
{
    cin >> n;
    for (int i = 1; i < n; i++)
    {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v), g[v].push_back(u);
    }
    dfs(1, 0);
    cout << zj << '\n';
    return 0;
}
相关推荐
开心比对错重要7 分钟前
进程、线程、虚拟线程详解及线程个数设置
java·jvm·算法·面试
爱学大树锯18 分钟前
【594 · 字符串查找 II】
java·开发语言·算法
m0_6924571030 分钟前
图像噪点消除
人工智能·算法
2401_8414956432 分钟前
【Python高级编程】图着色动态可视化 APP
python·算法·matplotlib·tkinter·回溯法·图着色算法·动态可视化工具
youngee111 小时前
hot100-53搜索旋转排序数组
数据结构·算法·leetcode
烟雨梵兮1 小时前
-刷题小结19
算法
爱学大树锯1 小时前
1361 · 文字并排
算法
Tisfy1 小时前
LeetCode 2483.商店的最少代价:两次遍历 -> 一次遍历
算法·leetcode·题解·遍历
YGGP1 小时前
【Golang】LeetCode 279. 完全平方数
算法·leetcode
im_AMBER2 小时前
Leetcode 87 等价多米诺骨牌对的数量
数据结构·笔记·学习·算法·leetcode