最远距离(树的直径)

文章介绍了如何计算一个有效无向连通图(即树)中距离最远的两个点之间的距离,即树的直径。通过深度优先搜索(DFS)遍历树的结构,找到以某个点为根的子树中的最长路径,并更新全局最大值来得到树的直径。提供的C++代码示例展示了具体的实现方法。
摘要由CSDN通过智能技术生成

我们规定,如果一个无向连通图满足去掉其中的任意一条边都会使得该图变得不连通,则称该图为有效无向连通图

给定一个 n 个点 m 条边的有效无向连通图,点的编号为 1∼n,所有边的长度均为 1

两点之间的距离定义为两点之间的最短距离

请你计算,给定图中距离最远的两个点之间的距离。

输入格式

第一行包含两个整数 n,m

接下来 m 行,每行包含两个整数 a,b,表示点 a 和点 b 之间存在一条无向边。

输出格式

一个整数,表示给定图中距离最远的两个点之间的距离。

数据范围

前三个测试点满足 1≤n,m≤10

所有测试点满足 1≤n,m≤105, 1≤a,b≤na≠b

输入样例1:
4 3
1 2
1 3
1 4
输出样例1:
2
输入样例2:
5 4
1 2
2 3
3 4
3 5
输出样例2:
3
思考

去掉一条边就不连通了,有效无向连通图就是树,这里使用数组模拟链表存储树

最远的两个点的距离,有两种求法

  1. 求一个点到另外一个点的最长距离,加上这个点到一个点的最长距离,就是树的直径

  1. 把一个点当作根节点,求该点的子树最长距离,其中最长的两个的和就是树的直径

树的直径就是树中两点的最长距离

细节讲解,代码附带注解

代码
#include<iostream>
#include<cstring>
using namespace std;

const int N = 100010, M = N * 2;
int n, m;
int h[N], e[M], ne[M], idex;
int ans;

void add(int a, int b){
    e[idex] = b, ne[idex] = h[a], h[a] = idex++;
}

int dfs(int u, int fa){
    int d1 = 0, d2 = 0;    //d1最长的, d2第二长的
    for(int i = h[u]; i != -1; i = ne[i]){
        int j = e[i];     
        if(j == fa) continue;     //无向图,遍历到父节点就continue
        int d = dfs(j, u) + 1;       //再找子树的最长距离
        if(d >= d1) d2 = d1, d1 = d;   //距离更新
        else if(d > d2) d2 = d;
    }
    
    ans = max(ans, d1 + d2);
    return d1;
}

int main(){
    scanf("%d%d", &n, &m);
    
    memset(h, -1, sizeof h);
    for(int i = 0; i < m; i++){
        int a, b;
        scanf("%d%d", &a, &b);
        add(a, b), add(b, a);
    }
    
    dfs(1, -1);
    printf("%d", ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Libert_AC

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

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

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

打赏作者

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

抵扣说明:

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

余额充值