【图论】树的直径

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

方法一: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;
}
相关推荐
青山木5 小时前
Hot 100 ---腐烂的橘子
java·数据结构·后端·算法·leetcode·广度优先
未来之窗软件服务5 小时前
计算机考试-快速排序—东方仙盟
数据结构·算法·排序算法·仙盟创梦ide·东方仙盟
小龙报5 小时前
【优选算法】1. 水果成蓝 2.找到字符串中所有字母的异位词
java·c语言·数据结构·数据库·c++·redis·算法
txzrxz6 小时前
数论:排列数、组合数、费马小定理、逆元、同余定理
c++·算法·数论·组合数·费马小定理·逆元·排列数
xqqxqxxq6 小时前
LeetCode Hot100 双指针专项题解笔记
笔记·算法·leetcode
闪电悠米6 小时前
力扣hot100-54.螺旋矩阵-模拟边界控制详解
算法·leetcode·矩阵
变量未定义~6 小时前
虚拟节点-星石传送阵(4星)、强连通分量
数据结构·算法
IT方大同6 小时前
C语言分支与循环语句
c语言·开发语言·算法
待磨的钝刨7 小时前
深入理解主成分分析(PCA)
人工智能·线性代数·算法·机器学习
wWYy.8 小时前
算法:合并两个有序数组
数据结构·算法