树与图的深度优先遍历——AcWing.846树的重心

news2025/1/10 2:36:08

树与图的深度优先遍历

定义

从图的某个顶点出发,沿着一条路径尽可能深地访问图中顶点。

运用情况

  • 图的连通性判断。
  • 寻找特定路径或回路。

注意事项

  • 要标记已访问的节点,以避免重复访问导致死循环。
  • 对于有向图和无向图可能需要不同的处理。

解题思路

  • 也是可以用递归方法,从起始顶点开始,访问该顶点,标记为已访问,然后对其未访问的邻接顶点进行深度优先遍历。

例如,对于一棵树,从根节点开始深度优先遍历,先访问根节点,再递归访问左子树和右子树。在图中,比如从一个顶点出发,访问相邻顶点,再递归深入访问它们的相邻顶点,直到无法继续深入为止,然后回溯。

AcWing.846树的重心

题目描述

846. 树的重心 - AcWing题库

运行代码

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int MAXN = 100005;
int n, root, ans, maxChild;
vector<int> G[MAXN];
int dfs1(int u, int fa) {
    int size = 1;
    for (int v : G[u]) {
        if (v != fa) {
            size += dfs1(v, u);
        }
    }
    return size;
}
int dfs2(int u, int fa, int tot) {
    int size = 1, maxSubtree = 0;
    for (int v : G[u]) {
        if (v != fa) {
            int subtreeSize = dfs2(v, u, tot);
            maxSubtree = max(maxSubtree, subtreeSize);
            size += subtreeSize;
        }
    }
    maxSubtree = max(maxSubtree, tot - size);
    ans = min(ans, maxSubtree);
    return size;
}
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);
    }
    ans = n;
    dfs1(root = 1, 0);
    dfs2(root, 0, n);
    cout << ans << endl;
    return 0;
}

代码思路

找到一棵树的重心,并输出删除重心后,剩余各个连通块中点数的最大值。代码采用了两次深度优先搜索(DFS)的策略来实现这一目标。

  1. dfs1:第一次DFS是为了计算每个节点的子树大小(节点数)。从根节点开始,递归遍历每个子节点,并将子树的节点数累加到当前节点的子树大小中。

  2. dfs2:第二次DFS是为了确定删除每个节点后,剩余树的最大连通块大小。这次DFS不仅递归遍历每个子节点,还计算以当前节点为根的子树被删除后,剩余部分的最大连通块大小,并更新全局变量ans为所有可能情况中的最小值。

  3. 主函数:首先读取树的节点数n,然后建立无向图的邻接表表示。之后,从节点1开始进行两次DFS,最后输出ans作为删除重心后,剩余连通块中点数的最大值。

改进思路

  1. 初始化根节点:原代码中直接将root设为1,实际上在处理任意树结构时,可以选择任一节点作为起点,但最好明确指出这一点或者实现一个方法来自动选择一个合适的起点(如度最小的节点)。

  2. 减少全局变量使用:尽量减少全局变量的使用,可以将ansG作为参数传递给函数,提高代码的封装性和可重用性。

  3. 优化输出逻辑:在dfs2中直接记录并更新最小的最大连通块大小,避免不必要的全局变量更新。

改进代码(AI生成)

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int MAXN = 100005;
vector<int> G[MAXN];
pair<int, int> findCentroid(int u, int fa, int tot, vector<int>& subtreeSize) {
    int size = 1, maxSubtree = 0;
    for (int v : G[u]) {
        if (v != fa) {
            auto [subtreeSz, _] = findCentroid(v, u, tot, subtreeSize);
            size += subtreeSz;
            maxSubtree = max(maxSubtree, subtreeSz);
        }
    }
    maxSubtree = max(maxSubtree, tot - size);
    subtreeSize[u] = size;
    return {size, maxSubtree};
}
int main() {
    int n;
    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);
    }
    vector<int> subtreeSize(n + 1, 0);
    auto [_, ans] = findCentroid(1, 0, n, subtreeSize);  
    cout << ans << endl;
    return 0;
}

其它代码

#include<iostream>
#include<cstring>
using namespace std;
const int N=100010;
int h[N],e[N*2],ne[N*2],idx,ans=N;
bool st[N];
int n;
void add(int a,int b)
{
    e[idx]=b;ne[idx]=h[a],h[a]=idx++;
}
int dfs(int u)
{
    st[u]=true;
    int size=0,sum=0;
    for(int i=h[u];i!=-1;i=ne[i])
    {
        int j=e[i];
        if(st[j]) continue;
        int s=dfs(j);
        size=max(size,s);
        sum+=s;
    }
    size=max(size,n-sum-1);
    ans=min(ans,size);
    return sum+1;
}
int main()
{
    memset(h, -1, sizeof h);
    cin>>n;
    for(int i=0;i<n-1;i++)
    {
        int a,b;cin>>a>>b;
        add(a,b),add(b,a);
    }
    dfs(1);
    cout<<ans<<endl;
    return 0;
}

代码思路

数据结构与初始化

  1. 使用邻接表表示无向树结构。h[N]数组用于存储每个节点的边链表的头指针,初始值为-1;e[N*2]和ne[N*2]分别存储边的目标节点和下一条边的索引,idx用来追踪当前使用的边索引;st[N]数组标记节点是否已被访问过。
  2. N定义为节点数的上限,初始化为100010。
  3. 全局变量ans初始化为N,用于记录删除某个节点后,剩余各个连通块中点数的最大值,初始化为一个较大的值以便后续更新。

函数定义
add(int a, int b)函数用于添加边,构建无向图。参数a和b分别代表连接的两个节点。
主要逻辑

  1. 读取输入:读取节点数n,然后读取n-1条边的连接关系,构造无向树。
  2. 深度优先搜索(DFS):定义dfs(int u)函数,用于递归地遍历以节点u为根的子树,并计算以下内容:遍历子树中的每个节点,跳过已访问的节点。
  3. 计算每个子树的节点数(大小),并记录当前子树的最大节点数size。
  4. 计算以当前节点为根的子树的节点总和sum。
  5. 更新最大连通块的大小,考虑当前节点作为分割点时的情况,即size=max(size, n-sum-1),其中n-sum-1表示除了当前子树以外的其他节点数。
  6. 返回当前子树的节点数加1(包括根节点自己)。
  7. 寻找重心并输出结果:从根节点(这里假设为节点1)开始调用dfs函数。遍历结束后,ans中存储的就是删除任一节点后,剩余各个连通块中点数的最大值。最后输出ans。

优化与注意事项

  1. 代码中通过双向连边构建无向图,但在树结构中,实际上只需要单向连边即可,不过这不影响算法的正确性。
  2. 该算法通过一次深度优先遍历完成任务,时间复杂度为O(n),是较为高效的解法。
  3. 代码中没有显式地寻找并标识重心,而是直接计算并输出了删除任一节点后最不利情况下的连通块大小,这在逻辑上等效于找到重心的概念,但并未直接指出哪个节点是重心。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1834310.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mysql数据库中触发器的使用

一、修改分隔符号 delimiter $$或者是//或者~~都行 二、创建触发器函数名称 create trigger 函数名 三、什么样的操作出发&#xff0c;操作那个表 after&#xff1a;.....之后触发 befor&#xff1a;.....之前触发 insert&#xff1a; 插入触发 update&#xff1a;修改被触发 d…

鸿蒙APP开发的技术难点

鸿蒙APP开发的技术难点主要体现在以下几个方面&#xff0c;鸿蒙APP开发是一项技术难度较高的工作&#xff0c;需要开发者具备扎实的编程基础、分布式开发能力和学习新技术的意愿。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1. 多…

充电宝什么牌子好?买多少毫安充电宝合适?这几个误区别踩!

在选择充电宝时&#xff0c;很多消费者常常被各种品牌和容量规格搞得眼花缭乱。不少人认为&#xff0c;容量越大越好&#xff0c;但事实并非如此。其实&#xff0c;根据日常使用需求&#xff0c;选择10000毫安的充电宝已经足够应对大多数情况。10000毫安的充电宝不仅能够满足手…

css-padding

文章目录 paddingpadding与元素的尺寸对于block块状水平元素复杂关系影响元素尺寸不影响元素尺寸最小宽度显示 关系总结 对于inline内联水平元素复杂关系水平padding影响尺寸垂直padding影响背景色区域 padding负值和百分比值负值百分比值inline水平元素的padding的百分比值空i…

WPF 深入理解三、控件结构

控件结构 演示&#xff1a; 思考疑问 为什么有一些元素是Content显示内容,而一些元素是Text显示内容? 凡是继承于Contentcontrol的控件,他们的定义内容用Content&#xff0c;除了TextBlock使用的是Text,大部分都是Content设置其显示内容。 为什么有一些元素有Padding,而一些元…

铁砧帝国延迟高?铁砧帝国延迟严重这样解决

铁砧帝国是一款少见的多人在线游戏&#xff0c;游戏能支持上千名玩家建立帝国并互相作战。而且这款游戏在细节方面也做足准备&#xff0c;设计了攻城梯和攻城锤等设备&#xff0c;以攻破坚固的城墙和要塞&#xff0c;不过具体获取方法就需要玩家自己摸索。因为最近开放了测试申…

Vue3基础介绍

文章目录 一、简介1、简介2、性能提升3、源码升级4、拥抱TypeScript5、新特性 二、创建Vue3.0工程1、使用vue-cli创建2、使用vite创建 三、分析工程结构1、main.js2、组件中 一、简介 1、简介 2020年9月18日&#xff0c;Vue.js发布3.0版本&#xff0c;代号(One Piece)海贼王 …

K8sGPT+Ollama:免费的 Kubernetes 自动化诊断方案

周末检查博客草稿&#xff0c;发现了这篇。记得当时是与 Kubernetes 自动化诊断工具&#xff1a;k8sgpt-operator 一起写的&#xff0c;算算过去了一年之久&#xff0c;这拖延症也算是病入膏肓了。原本想使用 K8sGPT LocalAI 的方案&#xff0c;由于之前试过 Ollama&#xff0…

OpenMMlab AI实战营第五、六期培训

OpenMMlab AI实战营第五、六期培训 OpenMMlab实战营第五、六次课2023.2.7-9学习参考第五次课笔记第六次课笔记一、什么是语义分割二、语义分割 v.s. 实例分割 v.s. 全景分割三、语义分割经典模型1.语义分割的基本思路2.**复用卷积计算**3.全连接层的卷积化4.预测图的升采样5.双…

Stable Diffusion 3 Medium 正式开源,用户对此产品评价如何?

前两天 Stability.AI 终于开源了 Stable Diffusion 3&#xff0c;虽然只是中杯的 Medium 版本&#xff0c;没有放出当初宣布的 8B 版本[1]&#xff0c;但也在很多方面取得了进步。本想第一时间尝鲜测试&#xff0c;但这几天出差在外&#xff0c;使用颇不方便。 正好老朋友揽睿…

HTTP/3 协议学习

前一篇&#xff1a; HTTP/2 协议学习-CSDN博客 HTTP/3 协议介绍 HTTP/3 是互联网上用于传输超文本的协议 HTTP 的第三个主要版本。它是 HTTP/2 的后继者&#xff0c;旨在进一步提高网络性能和安全性。HTTP/3 与前两个版本的主要区别在于它使用了一个完全不同的底层传输协议—…

安泰电压放大器的选型原则是什么

电压放大器是电子电路中常用的一种器件&#xff0c;主要用于放大输入电压信号。在选型电压放大器时&#xff0c;需要考虑以下几个原则。 根据应用需求确定放大倍数。放大倍数是指输出电压与输入电压之间的倍数关系&#xff0c;也称为增益。不同的应用场景对放大倍数的要求不同&…

3个火火火的AI项目,开源了!

友友们&#xff0c;今天我要给你们安利三个超酷的开源项目&#xff0c;它们都和AI有关&#xff0c;而且每一个都能让你的日常生活变得更加有趣和便捷&#xff01;(最近AI绘图又又超神了&#xff0c;分享以下美图养眼) 01 字节出品&#xff0c;文字转语音Seed-TTS 字节推出了一…

Ubuntu,Centos,Linux服务器安装Mellanox MCX653105A IB网卡HCA卡驱动

Mellanox 官方驱动下载地址 https://network.nvidia.com/products/infiniband-drivers/linux/mlnx_ofed/ 选择对应操作系统 官方链接速度比较慢&#xff0c;推荐个友商的下载地址 https://support.xfusion.com/support/#/zh/rack-servers/2288h-v5-pid-21872244/software …

【算法专题--链表】K个一组翻转链表 -- 高频面试题(图文详解,小白一看就懂!!!)

目录 一、前言 二、题目描述 三、解题方法 ⭐双指针 -- 采用哨兵位头节点 &#x1f95d; 什么是哨兵位头节点&#xff1f; &#x1f34d; 案例图解 四、总结与提炼 五、共勉 一、前言 K个一组翻转链表 这道题&#xff0c;可以说是--链表专题--&#xff0c;最经典…

Java内存模型(JMM)详解

文章目录 1、Java内存模型2、JMM的核心概念1&#xff09;主内存与工作内存2&#xff09;内存可见性3&#xff09;JMM的三大特性&#xff1a;原子性、可见性、有序性。 3、JMM中的八种操作4、Happens-before 规则5、样例&#xff1a; 1、Java内存模型 Java内存模型&#xff08;…

电脑文件防泄密软件——天锐绿盾 - 中科数安—— 哪个好

在选择电脑文件防泄密软件时&#xff0c;天锐绿盾和中科数安都是值得考虑的选项。以下是对这两款软件的详细比较&#xff1a; www.drhchina.com PC地址&#xff1a; https://isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c5dfedee 功能全面性&#xff1a; 天锐…

QT工作笔记

文章目录 QDialog的accept()和reject()介绍QPushButton提示属性样式表QComboBox QDialog的accept()和reject()介绍 accept() 和reject() 这两个槽函数都会和close() 一样关闭dialogaccept() 关闭后 返回了Dialog::Acceptedreject() 关闭后 返回了Dialog::Rejected这样当我们需…

SpringBoot修改banner

在resources目录下创建banner.txt文件 到该网站下选择banner https://www.bootschool.net/ascii-art 点击拷贝&#xff1a; 粘贴到banner.txt中&#xff0c;保存 重新运行项目即可&#xff1a;

ES升级--03-- IK分词器

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 IK分词器1. IK分词器 下载https://github.com/infinilabs/analysis-ik/releases 2. 创建文件夹 analysis-ik3.把zip包放至该目录下 解压4. 删除zip包5、重启Elastic…