首页 > 其他分享 >树的直径

树的直径

时间:2023-04-06 22:12:35浏览次数:48  
标签:远距离 int up 直径 d2 节点 d1

旅游规划

预处理

我们先确定一个点为根节点,我们统计一下从当前点开始往下走能走到的最远距离和次远距离,然后我们再dfs一遍预处理出来,一个点向上能走到的最远距离。

1、对于第一个预处理我们可以直接用树的直径的板子求得

2、对于第二个预处理我们做如下考虑

因为我们是求向上走能走的最大距离,所以我们是从上往下去更新的,对于当前节点的每个儿子节点,他们向上走可以转化为父节点怎么走的情况

WechatIMG841.jpeg

对于u这个节点我们要找到出了e这条边外,其他u节点连接的点向下走的最远距离,或者向上走的最远距离

这里向上走的最远距离我们已经有了,关键是找到除了j这一点外,其他向下走能走到的最远距离,这里可以分两种情况进行讨论,第一种是如果走j就是最大的话,我们就用次小值进行更新,如果不是最大的我们就直接用最大值更新,这里还有一个问题就是我们如何确定j是不是往下走最大的呢?我们在第一个预处理过程中可以用一个数组记录一下当前点往下走那个点是最大的这样的话我们就完成了所有的预处理

WechatIMG842.jpeg
WechatIMG843.jpeg

统计答案

我们从前往后枚举每一个点,当一个点向下走的最大距离加向上走的最大距离是直径时说明这个点就在树的直径上

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;
const int N = 2e5 + 10, M = N * 2;
int h[N], e[M], ne[M], idx, n;

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

int d1[N], d2[N], p[N], up[N], D;

//求树的直径,dfs一遍维护,每个点向下走能走的最远距离d1和次远距离d2
void dfs_d(int u, int fa)
{
    for(int i = h[u]; i != -1; i = ne[i])
    {
        int j = e[i];
        if(j != fa)
        {
            //从下往上算,因为我们要想知道父节点往下走的最远距离,需要
            //先知道,子节点向下走的最远距离,然后从下向上传递信息更新
            dfs_d(j, u);
            int d = d1[j] + 1;
            //如果当前子节点+1的距离大于原来u节点存的最大距离的话
            //这时我们就需要去更新u节点的最大距离,这里不要忘记更
            //更新一下次大距离
            if(d > d1[u])
            {
                d2[u] = d1[u];
                d1[u] = d;
                p[u] = j;
            }
            //否则我们退而求其次看当前节点+1的距离能否更新次大距离,
            //如果能就将次大距离更新
            else if(d > d2[u])  d2[u] = d;
        }
    }
    //每次算完更新一下任意两个端点之间的最大距离
    D = max(D, d1[u] + d2[u]);
}


void dfs_up(int u, int fa)
{
    for(int i = h[u]; i != -1; i = ne[i])
    {
        int j = e[i];
        if(j != fa)
        {
            //自上而下更新
            //首先,子节点的向上走能走到的最远距离可以先
            //向上走一步到u节点,然后我们需要找到除了u-j
            //这一条边外其他节点能走的最大值
            //这里分为两种情况,一种是,u节点继续向上走,
            //两一种就是u节点除去走过的那一条,向下走的最
            //大值, 所以这里我们又会有不同的情况,当我们
            //走过的条边是我们从u点开始向下走的最大的话我
            //就不能用d1[u]去更新,而需要用d2[u]去更新,
            //反之我们直接用d1[u]去更新
            up[j] = up[u] + 1;
            if(j == p[u])   up[j] = max(up[j], d2[u] + 1);
            else    up[j] = max(up[j], d1[u] + 1);
            dfs_up(j , u);
        }
    }
}

int main()
{
    cin >> n;
    memset(h, -1, sizeof h);
    for(int i = 0; i < n - 1; ++ i)
    {
        int a, b;scanf("%d%d", &a, &b);
        add(a, b);
        add(b, a);
    }
    dfs_d(0, -1);
    dfs_up(0, -1);
    for(int i = 0; i < n; ++ i) 
    {
        int a[3] = {d1[i], d2[i], up[i]};
        sort(a, a + 3);
        if(a[2] + a[1] == D)    printf("%d\n", i);
    }
    return 0;
}

标签:远距离,int,up,直径,d2,节点,d1
From: https://www.cnblogs.com/cxy8/p/17294411.html

相关文章

  • D. Book of Evil(树的直径+换根dp)
    #include<bits/stdc++.h>#definedebug1(a)cout<<#a<<'='<<a<<endl;#definedebug2(a,b)cout<<#a<<"="<<a<<""<<#b<<"="<&......
  • un-resolved CFD-DEM网格尺寸为颗粒直径的3倍以上
    依据颗粒与流体网格的尺寸,目前在未解析CFD-DEM模型中,流体空隙率算法主要有三种:PCM(ParticleCentroidMethod)、DPVM(DividedParticleVolume Method)和SKM(StatisticalKe......
  • TZOJ数据结构实验:树相同、左叶子和、倾斜度、直径、平衡二叉树、最小深度、层次构造二
    5429数据结构实验:树是否相同intisSameTree(structTreeNode*p,structTreeNode*q)//相同返回1,否则返回0{if(p==NULL&&q==NULL)return1;if(p==NULL||......
  • 树的直径
    能解决什么问题找出树中最长的路径算法思想任取一点,求该点到其他点的距离,找到离它最远的点u求u到其他点的距离,找到离u最远的点vu,v就是树的最长路径由反证法......
  • 大臣的旅费 【树的直径】【DFS】
    大臣的旅费Description很久以前,T王国空前繁荣。为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市。为节省经费,T国的大臣们经过思考,制定了一套优秀......
  • Comet OJ - Contest #9 & X Round 3 核心城市(树的直径)
    题目描述X国有 nn 座城市,n−1n−1 条长度为 11 的道路,每条道路连接两座城市,且任意两座城市都能通过若干条道路相互到达,显然,城市和道路形成了一棵树。X国国王决定将......
  • POJ 2631 Roads in the North(树的直径)
    DescriptionBuildingandmaintainingroadsamongcommunitiesinthefarNorthisanexpensivebusiness.Withthisinmind,theroadsarebuildsuchthatthereis......
  • leetcode-543二叉树直径
    //leetcodesubmitregionbegin(Prohibitmodificationanddeletion)/***Definitionforabinarytreenode.*publicclassTreeNode{*intval;*TreeNodeleft;......
  • 【DFS】LeetCode 543. 二叉树的直径
    题目链接543.二叉树的直径思路创建全局变量diameter以记录左子树高度加右子树高度,并在DFS过程中维护此变量。代码classSolution{intdiameter;publ......
  • 543. 二叉树的直径
    题目给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。注意:两结点之间的路径长度......