十二、树的直径

求树的的直径与求图的最长路是一样的。
一对点之间经过的所有节点和边会组成一条链,最长的一条链就是最长路,在树中,最长链就是树的直径。
对于解决这样的问题。我们一般用的是双DFS法,具体操作如下:

  1. 随便找一个点 x x x,搜索出离这个点最远的点 y y y
  2. y y y 开始搜索,找出离 y y y 最远的点 z z z
  3. z z z y y y 就是直径的两个端点。

分析一下这个思路是否满足所有情况:

  1. 如果 x 在 y 到 z 的路径上,假设这条路不是直径,那就说明存在一个离 x 更远的点 p,那这样的话第一遍DFS会在 p 处停止,而不是在 y 处。所以不存在比 y-z 更长的链。
  2. 如果 x 不在 y 到 z 的路径上,则有:
    1. 如果 x 到与其最远的点 p 这条链 x-p 与直径相交,这就意味着交点到 y 或 z 的距离小于到 x 或 p 的距离,这样的话有悖于“直径最长”这一性质。
    2. 如果 x-y 与真正的直径没有交点,那这样的话从直径离 x-y 近的一端引一条路到 x-y 上,这条路会长于直径,再次有悖。

代码实现如下:
每次输入x, y, d,表示从 x 到 y 距离为 d。

#include<bits/stdc++.h>

using namespace std;

struct Edge {
    int to, dis;

    Edge(int x, int y) {
        to = x, dis = y;
    }
};

vector<Edge> mp[10000];
int fl[10000];

void addEdge(int x, int y, int dis) {
    mp[x].push_back(Edge(y, dis));
    mp[y].push_back(Edge(x, dis));
}

int maxDis = 0, maxNum = 1;

void dfs(int now, int sum) {
    if (sum > maxDis) {
        maxDis = sum;
        maxNum = now;
    }
    for (int i = 0; i < mp[now].size(); i++) {
        if (fl[mp[now][i].to] != 1) {
            fl[mp[now][i].to] = 1;
            dfs(mp[now][i].to, sum + mp[now][i].dis);
        }
    }
}

int main() {
    int n, x, y, d;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> x >> y >> d;
        addEdge(x, y, d);
    }
    dfs(1, 0);
    memset(fl, 0, sizeof fl);
    int t = maxNum;
    maxNum = 0, maxDis = 0;
    dfs(t, 0);
    cout << "\n" << t << "\t" << maxNum;
    return 0;
}
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fanxinfx2

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值