【图论】树的直径

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

方法一: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;
}
相关推荐
倒头就睡的小比特1 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!1 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼1 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
旖旎夜光1 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark1 天前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her11 天前
并查集-听课笔记
笔记·算法·并查集
码流子1 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven1 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark1 天前
从算法设计模式看编程思维的抽象能力4
算法
2601_962218611 天前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法